blob: 22dbc7fd55aad4fb6d29f09a4e2a27e838504cb5 [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,
36}
37
38#[derive(Debug, Clone, Eq, PartialEq)]
39pub struct MutTy {
40 pub ty: Ty,
41 pub mutability: Mutability,
42}
43
David Tolnayf4bbbd92016-09-23 14:41:55 -070044#[derive(Debug, Copy, Clone, Eq, PartialEq)]
David Tolnayb79ee962016-09-04 09:39:20 -070045pub enum Mutability {
46 Mutable,
47 Immutable,
48}
49
David Tolnay771ecf42016-09-23 19:26:37 -070050/// A "Path" is essentially Rust's notion of a name.
51///
52/// It's represented as a sequence of identifiers,
53/// along with a bunch of supporting information.
54///
55/// E.g. `std::cmp::PartialEq`
David Tolnayb79ee962016-09-04 09:39:20 -070056#[derive(Debug, Clone, Eq, PartialEq)]
57pub struct Path {
58 pub global: bool,
59 pub segments: Vec<PathSegment>,
60}
61
David Tolnaydaaf7742016-10-03 11:11:43 -070062impl<T> From<T> for Path
63 where T: Into<PathSegment>
64{
David Tolnay84aa0752016-10-02 23:01:13 -070065 fn from(segment: T) -> Self {
66 Path {
67 global: false,
68 segments: vec![segment.into()],
69 }
70 }
71}
72
David Tolnayb79ee962016-09-04 09:39:20 -070073/// A segment of a path: an identifier, an optional lifetime, and a set of types.
74///
75/// E.g. `std`, `String` or `Box<T>`
76#[derive(Debug, Clone, Eq, PartialEq)]
77pub struct PathSegment {
78 pub ident: Ident,
79 pub parameters: PathParameters,
80}
81
David Tolnaydaaf7742016-10-03 11:11:43 -070082impl<T> From<T> for PathSegment
83 where T: Into<Ident>
84{
David Tolnay84aa0752016-10-02 23:01:13 -070085 fn from(ident: T) -> Self {
David Tolnayb79ee962016-09-04 09:39:20 -070086 PathSegment {
David Tolnay84aa0752016-10-02 23:01:13 -070087 ident: ident.into(),
David Tolnayb79ee962016-09-04 09:39:20 -070088 parameters: PathParameters::none(),
89 }
90 }
91}
92
93/// Parameters of a path segment.
94///
95/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
96#[derive(Debug, Clone, Eq, PartialEq)]
97pub enum PathParameters {
98 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
99 AngleBracketed(AngleBracketedParameterData),
100 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
101 Parenthesized(ParenthesizedParameterData),
102}
103
104impl PathParameters {
105 pub fn none() -> Self {
106 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
107 }
108}
109
110/// A path like `Foo<'a, T>`
111#[derive(Debug, Clone, Eq, PartialEq, Default)]
112pub struct AngleBracketedParameterData {
113 /// The lifetime parameters for this path segment.
114 pub lifetimes: Vec<Lifetime>,
115 /// The type parameters for this path segment, if present.
116 pub types: Vec<Ty>,
117 /// Bindings (equality constraints) on associated types, if present.
118 ///
119 /// E.g., `Foo<A=Bar>`.
120 pub bindings: Vec<TypeBinding>,
121}
122
123/// Bind a type to an associated type: `A=Foo`.
124#[derive(Debug, Clone, Eq, PartialEq)]
125pub struct TypeBinding {
126 pub ident: Ident,
127 pub ty: Ty,
128}
129
130/// A path like `Foo(A,B) -> C`
131#[derive(Debug, Clone, Eq, PartialEq)]
132pub struct ParenthesizedParameterData {
133 /// `(A, B)`
134 pub inputs: Vec<Ty>,
135 /// `C`
136 pub output: Option<Ty>,
137}
138
139#[derive(Debug, Clone, Eq, PartialEq)]
140pub struct PolyTraitRef {
141 /// The `'a` in `<'a> Foo<&'a T>`
142 pub bound_lifetimes: Vec<LifetimeDef>,
143 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
144 pub trait_ref: Path,
145}
146
147/// The explicit Self type in a "qualified path". The actual
148/// path, including the trait and the associated item, is stored
149/// separately. `position` represents the index of the associated
150/// item qualified with this Self type.
151///
152/// ```rust,ignore
153/// <Vec<T> as a::b::Trait>::AssociatedItem
154/// ^~~~~ ~~~~~~~~~~~~~~^
155/// ty position = 3
156///
157/// <Vec<T>>::AssociatedItem
158/// ^~~~~ ^
159/// ty position = 0
160/// ```
161#[derive(Debug, Clone, Eq, PartialEq)]
162pub struct QSelf {
163 pub ty: Box<Ty>,
David Tolnaydaaf7742016-10-03 11:11:43 -0700164 pub position: usize,
David Tolnayb79ee962016-09-04 09:39:20 -0700165}
166
167#[derive(Debug, Clone, Eq, PartialEq)]
168pub struct BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700169 pub unsafety: Unsafety,
170 pub abi: Option<Abi>,
David Tolnayb79ee962016-09-04 09:39:20 -0700171 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700172 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700173 pub output: FunctionRetTy,
David Tolnay292e6002016-10-29 22:03:51 -0700174 pub variadic: bool,
David Tolnayb79ee962016-09-04 09:39:20 -0700175}
176
David Tolnayb8d8ef52016-10-29 14:30:08 -0700177#[derive(Debug, Copy, Clone, Eq, PartialEq)]
178pub enum Unsafety {
179 Unsafe,
180 Normal,
181}
182
183#[derive(Debug, Clone, Eq, PartialEq)]
184pub enum Abi {
185 Named(String),
186 Extern,
187}
188
David Tolnay62f374c2016-10-02 13:37:00 -0700189/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700190///
191/// E.g. `bar: usize` as in `fn foo(bar: usize)`
192#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay62f374c2016-10-02 13:37:00 -0700193pub struct BareFnArg {
194 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700195 pub ty: Ty,
196}
197
198#[derive(Debug, Clone, Eq, PartialEq)]
199pub enum FunctionRetTy {
200 /// Return type is not specified.
201 ///
202 /// Functions default to `()` and
203 /// closures default to inference. Span points to where return
204 /// type would be inserted.
205 Default,
206 /// Everything else
207 Ty(Ty),
208}
209
David Tolnay86eca752016-09-04 11:26:41 -0700210#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700211pub mod parsing {
212 use super::*;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700213 #[cfg(feature = "full")]
214 use ConstExpr;
David Tolnay3cb23a92016-10-07 23:02:21 -0700215 use constant::parsing::const_expr;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700216 #[cfg(feature = "full")]
217 use expr::parsing::expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700218 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700219 use ident::parsing::ident;
David Tolnayb8d8ef52016-10-29 14:30:08 -0700220 use lit::parsing::quoted_string;
David Tolnay9d8f1972016-09-04 11:58:48 -0700221 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700222
David Tolnayb5a7b142016-09-13 22:46:39 -0700223 named!(pub ty -> Ty, alt!(
David Tolnayd040d772016-10-25 21:33:51 -0700224 ty_paren // must be before ty_tup
225 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700226 ty_path // must be before ty_poly_trait_ref
227 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700228 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700229 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700230 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700231 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700232 ty_ptr
233 |
234 ty_rptr
235 |
236 ty_bare_fn
237 |
238 ty_never
239 |
240 ty_tup
241 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700242 ty_poly_trait_ref
David Tolnay9d8f1972016-09-04 11:58:48 -0700243 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700244 ty_impl_trait
David Tolnay9d8f1972016-09-04 11:58:48 -0700245 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700246
David Tolnayb5a7b142016-09-13 22:46:39 -0700247 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700248 punct!("[") >>
249 elem: ty >>
250 punct!("]") >>
David Tolnay16709ba2016-10-05 23:11:32 -0700251 (Ty::Slice(Box::new(elem)))
David Tolnay9d8f1972016-09-04 11:58:48 -0700252 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700253
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700254 #[cfg(not(feature = "full"))]
David Tolnayfa94b6f2016-10-05 23:26:11 -0700255 named!(ty_array -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700256 punct!("[") >>
257 elem: ty >>
258 punct!(";") >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700259 len: const_expr >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700260 punct!("]") >>
David Tolnayfa94b6f2016-10-05 23:26:11 -0700261 (Ty::Array(Box::new(elem), len))
262 ));
263
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700264 #[cfg(feature = "full")]
265 named!(ty_array -> Ty, do_parse!(
266 punct!("[") >>
267 elem: ty >>
268 punct!(";") >>
269 len: alt!(
270 terminated!(const_expr, punct!("]"))
271 |
272 terminated!(expr, punct!("]")) => { ConstExpr::Other }
273 ) >>
274 (Ty::Array(Box::new(elem), len))
275 ));
276
David Tolnayb5a7b142016-09-13 22:46:39 -0700277 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700278 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700279 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700280 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700281 |
David Tolnay10413f02016-09-30 09:12:02 -0700282 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700283 ) >>
284 target: ty >>
285 (Ty::Ptr(Box::new(MutTy {
286 ty: target,
287 mutability: mutability,
288 })))
289 ));
290
David Tolnayb5a7b142016-09-13 22:46:39 -0700291 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700292 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700293 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700294 mutability: mutability >>
295 target: ty >>
296 (Ty::Rptr(life, Box::new(MutTy {
297 ty: target,
298 mutability: mutability,
299 })))
300 ));
301
David Tolnayb5a7b142016-09-13 22:46:39 -0700302 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay4f121832016-10-25 21:33:36 -0700303 lifetimes: opt_vec!(do_parse!(
304 keyword!("for") >>
305 punct!("<") >>
306 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
307 punct!(">") >>
308 (lifetimes)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700309 )) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700310 unsafety: unsafety >>
311 abi: option!(abi) >>
David Tolnay4f121832016-10-25 21:33:36 -0700312 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700313 punct!("(") >>
David Tolnay292e6002016-10-29 22:03:51 -0700314 inputs: separated_list!(punct!(","), fn_arg) >>
315 trailing_comma: option!(punct!(",")) >>
316 variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700317 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700318 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700319 punct!("->"),
320 ty
321 )) >>
322 (Ty::BareFn(Box::new(BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700323 unsafety: unsafety,
324 abi: abi,
David Tolnay9d8f1972016-09-04 11:58:48 -0700325 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700326 inputs: inputs,
327 output: match output {
328 Some(ty) => FunctionRetTy::Ty(ty),
329 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700330 },
David Tolnay292e6002016-10-29 22:03:51 -0700331 variadic: variadic.is_some(),
David Tolnay9d8f1972016-09-04 11:58:48 -0700332 })))
333 ));
334
David Tolnayb5a7b142016-09-13 22:46:39 -0700335 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700336
David Tolnayb5a7b142016-09-13 22:46:39 -0700337 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700338 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700339 elems: terminated_list!(punct!(","), ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700340 punct!(")") >>
341 (Ty::Tup(elems))
342 ));
343
David Tolnay6414da72016-10-08 00:55:17 -0700344 named!(ty_path -> Ty, do_parse!(
345 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700346 parenthesized: cond!(
347 qpath.1.segments.last().unwrap().parameters == PathParameters::none(),
348 option!(parenthesized_parameter_data)
349 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700350 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
351 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700352 let (qself, mut path) = qpath;
353 if let Some(Some(parenthesized)) = parenthesized {
354 path.segments.last_mut().unwrap().parameters = parenthesized;
355 }
356 let path = Ty::Path(qself, path);
David Tolnay6414da72016-10-08 00:55:17 -0700357 if bounds.is_empty() {
358 path
359 } else {
360 Ty::ObjectSum(Box::new(path), bounds)
361 }
362 })
363 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700364
David Tolnayf6c74402016-10-08 02:31:26 -0700365 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
366 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700367 inputs: terminated_list!(punct!(","), ty) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700368 punct!(")") >>
369 output: option!(preceded!(
370 punct!("->"),
371 ty
372 )) >>
373 (PathParameters::Parenthesized(
374 ParenthesizedParameterData {
375 inputs: inputs,
376 output: output,
377 },
378 ))
379 ));
380
David Tolnay9636c052016-10-02 17:11:17 -0700381 named!(pub qpath -> (Option<QSelf>, Path), alt!(
382 map!(path, |p| (None, p))
383 |
384 do_parse!(
385 punct!("<") >>
386 this: map!(ty, Box::new) >>
387 path: option!(preceded!(
388 keyword!("as"),
389 path
390 )) >>
391 punct!(">") >>
392 punct!("::") >>
393 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
394 ({
395 match path {
396 Some(mut path) => {
397 let pos = path.segments.len();
398 path.segments.extend(rest);
399 (Some(QSelf { ty: this, position: pos }), path)
400 }
401 None => {
402 (Some(QSelf { ty: this, position: 0 }), Path {
403 global: false,
404 segments: rest,
405 })
406 }
David Tolnayb79ee962016-09-04 09:39:20 -0700407 }
David Tolnay9636c052016-10-02 17:11:17 -0700408 })
409 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700410 |
411 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700412 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700413
David Tolnay4f0f2512016-10-30 09:28:14 -0700414 named!(ty_poly_trait_ref -> Ty, map!(
David Tolnay8eb6c452016-10-30 13:19:15 -0700415 separated_nonempty_list!(punct!("+"), ty_param_bound),
416 Ty::PolyTraitRef
David Tolnay6414da72016-10-08 00:55:17 -0700417 ));
418
David Tolnayb5a7b142016-09-13 22:46:39 -0700419 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700420 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700421 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
422 (Ty::ImplTrait(elem))
423 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700424
David Tolnayb5a7b142016-09-13 22:46:39 -0700425 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700426 punct!("(") >>
427 elem: ty >>
428 punct!(")") >>
429 (Ty::Paren(Box::new(elem)))
430 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700431
David Tolnay47a877c2016-10-01 16:50:55 -0700432 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700433 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700434 |
435 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700436 ));
437
David Tolnayb5a7b142016-09-13 22:46:39 -0700438 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700439 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700440 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
441 (Path {
442 global: global.is_some(),
443 segments: segments,
444 })
445 ));
446
David Tolnay9636c052016-10-02 17:11:17 -0700447 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700448 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700449 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700450 punct!("<") >>
451 lifetimes: separated_list!(punct!(","), lifetime) >>
452 types: opt_vec!(preceded!(
453 cond!(!lifetimes.is_empty(), punct!(",")),
454 separated_nonempty_list!(
455 punct!(","),
456 terminated!(ty, not!(peek!(punct!("="))))
457 )
458 )) >>
459 bindings: opt_vec!(preceded!(
460 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
461 separated_nonempty_list!(punct!(","), type_binding)
462 )) >>
David Tolnay82a47d52016-10-30 13:01:38 -0700463 cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700464 punct!(">") >>
465 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700466 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700467 parameters: PathParameters::AngleBracketed(
468 AngleBracketedParameterData {
469 lifetimes: lifetimes,
470 types: types,
471 bindings: bindings,
472 }
473 ),
474 })
475 )
476 |
David Tolnay84aa0752016-10-02 23:01:13 -0700477 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700478 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700479 map!(alt!(
480 keyword!("super")
481 |
482 keyword!("self")
483 |
484 keyword!("Self")
485 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700486 ));
487
David Tolnayb5a7b142016-09-13 22:46:39 -0700488 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700489 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700490 punct!("=") >>
491 ty: ty >>
492 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700493 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700494 ty: ty,
495 })
496 ));
497
David Tolnayb5a7b142016-09-13 22:46:39 -0700498 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700499 bound_lifetimes: bound_lifetimes >>
500 trait_ref: path >>
David Tolnay4f0f2512016-10-30 09:28:14 -0700501 parenthesized: option!(cond_reduce!(
David Tolnayf6c74402016-10-08 02:31:26 -0700502 trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
David Tolnay4f0f2512016-10-30 09:28:14 -0700503 parenthesized_parameter_data
504 )) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700505 ({
506 let mut trait_ref = trait_ref;
David Tolnay4f0f2512016-10-30 09:28:14 -0700507 if let Some(parenthesized) = parenthesized {
David Tolnayf6c74402016-10-08 02:31:26 -0700508 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
509 }
510 PolyTraitRef {
511 bound_lifetimes: bound_lifetimes,
512 trait_ref: trait_ref,
513 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700514 })
515 ));
516
David Tolnay62f374c2016-10-02 13:37:00 -0700517 named!(pub fn_arg -> BareFnArg, do_parse!(
David Tolnayb0417d72016-10-25 21:46:35 -0700518 name: option!(do_parse!(
519 name: ident >>
520 punct!(":") >>
521 not!(peek!(tag!(":"))) >> // not ::
522 (name)
523 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700524 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700525 (BareFnArg {
526 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700527 ty: ty,
528 })
529 ));
David Tolnayb8d8ef52016-10-29 14:30:08 -0700530
531 named!(pub unsafety -> Unsafety, alt!(
532 keyword!("unsafe") => { |_| Unsafety::Unsafe }
533 |
534 epsilon!() => { |_| Unsafety::Normal }
535 ));
536
537 named!(pub abi -> Abi, do_parse!(
538 keyword!("extern") >>
539 name: option!(quoted_string) >>
540 (match name {
541 Some(name) => Abi::Named(name),
542 None => Abi::Extern,
543 })
544 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700545}
David Tolnay87d0b442016-09-04 11:52:12 -0700546
547#[cfg(feature = "printing")]
548mod printing {
549 use super::*;
550 use quote::{Tokens, ToTokens};
551
552 impl ToTokens for Ty {
553 fn to_tokens(&self, tokens: &mut Tokens) {
554 match *self {
David Tolnay16709ba2016-10-05 23:11:32 -0700555 Ty::Slice(ref inner) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700556 tokens.append("[");
557 inner.to_tokens(tokens);
558 tokens.append("]");
559 }
David Tolnayfa94b6f2016-10-05 23:26:11 -0700560 Ty::Array(ref inner, ref len) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700561 tokens.append("[");
562 inner.to_tokens(tokens);
563 tokens.append(";");
David Tolnayfa94b6f2016-10-05 23:26:11 -0700564 len.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700565 tokens.append("]");
566 }
567 Ty::Ptr(ref target) => {
568 tokens.append("*");
569 match target.mutability {
570 Mutability::Mutable => tokens.append("mut"),
571 Mutability::Immutable => tokens.append("const"),
572 }
573 target.ty.to_tokens(tokens);
574 }
575 Ty::Rptr(ref lifetime, ref target) => {
576 tokens.append("&");
577 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700578 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700579 target.ty.to_tokens(tokens);
580 }
581 Ty::BareFn(ref func) => {
582 func.to_tokens(tokens);
583 }
584 Ty::Never => {
585 tokens.append("!");
586 }
587 Ty::Tup(ref elems) => {
588 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700589 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700590 if elems.len() == 1 {
591 tokens.append(",");
592 }
593 tokens.append(")");
594 }
David Tolnayf69904a2016-09-04 14:46:07 -0700595 Ty::Path(None, ref path) => {
596 path.to_tokens(tokens);
597 }
598 Ty::Path(Some(ref qself), ref path) => {
599 tokens.append("<");
600 qself.ty.to_tokens(tokens);
601 if qself.position > 0 {
602 tokens.append("as");
David Tolnaydaaf7742016-10-03 11:11:43 -0700603 for (i, segment) in path.segments
604 .iter()
605 .take(qself.position)
606 .enumerate() {
David Tolnayf69904a2016-09-04 14:46:07 -0700607 if i > 0 || path.global {
608 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700609 }
David Tolnayf69904a2016-09-04 14:46:07 -0700610 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700611 }
David Tolnayf69904a2016-09-04 14:46:07 -0700612 }
613 tokens.append(">");
614 for segment in path.segments.iter().skip(qself.position) {
615 tokens.append("::");
616 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700617 }
618 }
David Tolnay6414da72016-10-08 00:55:17 -0700619 Ty::ObjectSum(ref ty, ref bounds) => {
620 ty.to_tokens(tokens);
621 for bound in bounds {
622 tokens.append("+");
623 bound.to_tokens(tokens);
624 }
625 }
626 Ty::PolyTraitRef(ref bounds) => {
627 tokens.append_separated(bounds, "+");
628 }
David Tolnay87d0b442016-09-04 11:52:12 -0700629 Ty::ImplTrait(ref bounds) => {
630 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700631 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700632 }
633 Ty::Paren(ref inner) => {
634 tokens.append("(");
635 inner.to_tokens(tokens);
636 tokens.append(")");
637 }
638 Ty::Infer => {
639 tokens.append("_");
640 }
641 }
642 }
643 }
644
David Tolnay47a877c2016-10-01 16:50:55 -0700645 impl ToTokens for Mutability {
646 fn to_tokens(&self, tokens: &mut Tokens) {
647 if let Mutability::Mutable = *self {
648 tokens.append("mut");
649 }
650 }
651 }
652
David Tolnay87d0b442016-09-04 11:52:12 -0700653 impl ToTokens for Path {
654 fn to_tokens(&self, tokens: &mut Tokens) {
655 for (i, segment) in self.segments.iter().enumerate() {
656 if i > 0 || self.global {
657 tokens.append("::");
658 }
659 segment.to_tokens(tokens);
660 }
661 }
662 }
663
664 impl ToTokens for PathSegment {
665 fn to_tokens(&self, tokens: &mut Tokens) {
666 self.ident.to_tokens(tokens);
667 self.parameters.to_tokens(tokens);
668 }
669 }
670
671 impl ToTokens for PathParameters {
672 fn to_tokens(&self, tokens: &mut Tokens) {
673 match *self {
674 PathParameters::AngleBracketed(ref parameters) => {
675 parameters.to_tokens(tokens);
676 }
677 PathParameters::Parenthesized(ref parameters) => {
678 parameters.to_tokens(tokens);
679 }
680 }
681 }
682 }
683
684 impl ToTokens for AngleBracketedParameterData {
685 fn to_tokens(&self, tokens: &mut Tokens) {
686 let has_lifetimes = !self.lifetimes.is_empty();
687 let has_types = !self.types.is_empty();
688 let has_bindings = !self.bindings.is_empty();
689 if !has_lifetimes && !has_types && !has_bindings {
690 return;
691 }
692
693 tokens.append("<");
694
695 let mut first = true;
696 for lifetime in &self.lifetimes {
697 if !first {
698 tokens.append(",");
699 }
700 lifetime.to_tokens(tokens);
701 first = false;
702 }
703 for ty in &self.types {
704 if !first {
705 tokens.append(",");
706 }
707 ty.to_tokens(tokens);
708 first = false;
709 }
710 for binding in &self.bindings {
711 if !first {
712 tokens.append(",");
713 }
714 binding.to_tokens(tokens);
715 first = false;
716 }
717
718 tokens.append(">");
719 }
720 }
721
722 impl ToTokens for TypeBinding {
723 fn to_tokens(&self, tokens: &mut Tokens) {
724 self.ident.to_tokens(tokens);
725 tokens.append("=");
726 self.ty.to_tokens(tokens);
727 }
728 }
729
730 impl ToTokens for ParenthesizedParameterData {
731 fn to_tokens(&self, tokens: &mut Tokens) {
732 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700733 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700734 tokens.append(")");
735 if let Some(ref output) = self.output {
736 tokens.append("->");
737 output.to_tokens(tokens);
738 }
739 }
740 }
741
742 impl ToTokens for PolyTraitRef {
743 fn to_tokens(&self, tokens: &mut Tokens) {
744 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700745 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700746 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700747 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700748 tokens.append(">");
749 }
750 self.trait_ref.to_tokens(tokens);
751 }
752 }
753
754 impl ToTokens for BareFnTy {
755 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay87d0b442016-09-04 11:52:12 -0700756 if !self.lifetimes.is_empty() {
David Tolnay4f121832016-10-25 21:33:36 -0700757 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700758 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700759 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700760 tokens.append(">");
761 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700762 self.unsafety.to_tokens(tokens);
763 self.abi.to_tokens(tokens);
David Tolnay4f121832016-10-25 21:33:36 -0700764 tokens.append("fn");
David Tolnay87d0b442016-09-04 11:52:12 -0700765 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700766 tokens.append_separated(&self.inputs, ",");
David Tolnay292e6002016-10-29 22:03:51 -0700767 if self.variadic {
768 if !self.inputs.is_empty() {
769 tokens.append(",");
770 }
771 tokens.append("...");
772 }
David Tolnay87d0b442016-09-04 11:52:12 -0700773 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700774 if let FunctionRetTy::Ty(ref ty) = self.output {
775 tokens.append("->");
776 ty.to_tokens(tokens);
777 }
778 }
779 }
780
David Tolnay62f374c2016-10-02 13:37:00 -0700781 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700782 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700783 if let Some(ref name) = self.name {
784 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700785 tokens.append(":");
786 }
787 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700788 }
789 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700790
791 impl ToTokens for Unsafety {
792 fn to_tokens(&self, tokens: &mut Tokens) {
793 match *self {
794 Unsafety::Unsafe => tokens.append("unsafe"),
795 Unsafety::Normal => {
796 // nothing
797 }
798 }
799 }
800 }
801
802 impl ToTokens for Abi {
803 fn to_tokens(&self, tokens: &mut Tokens) {
804 tokens.append("extern");
805 match *self {
806 Abi::Named(ref named) => named.to_tokens(tokens),
807 Abi::Extern => {}
808 }
809 }
810 }
David Tolnay87d0b442016-09-04 11:52:12 -0700811}