blob: 5f8ba37d114b4f766568518d617a76fc746d9098 [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 }
David Tolnay5332d4b2016-10-30 14:25:22 -0700108
109 pub fn is_empty(&self) -> bool {
110 match *self {
111 PathParameters::AngleBracketed(ref bracketed) => {
112 bracketed.lifetimes.is_empty() && bracketed.types.is_empty() && bracketed.bindings.is_empty()
113 }
114 PathParameters::Parenthesized(_) => false,
115 }
116 }
David Tolnayb79ee962016-09-04 09:39:20 -0700117}
118
119/// A path like `Foo<'a, T>`
120#[derive(Debug, Clone, Eq, PartialEq, Default)]
121pub struct AngleBracketedParameterData {
122 /// The lifetime parameters for this path segment.
123 pub lifetimes: Vec<Lifetime>,
124 /// The type parameters for this path segment, if present.
125 pub types: Vec<Ty>,
126 /// Bindings (equality constraints) on associated types, if present.
127 ///
128 /// E.g., `Foo<A=Bar>`.
129 pub bindings: Vec<TypeBinding>,
130}
131
132/// Bind a type to an associated type: `A=Foo`.
133#[derive(Debug, Clone, Eq, PartialEq)]
134pub struct TypeBinding {
135 pub ident: Ident,
136 pub ty: Ty,
137}
138
139/// A path like `Foo(A,B) -> C`
140#[derive(Debug, Clone, Eq, PartialEq)]
141pub struct ParenthesizedParameterData {
142 /// `(A, B)`
143 pub inputs: Vec<Ty>,
144 /// `C`
145 pub output: Option<Ty>,
146}
147
148#[derive(Debug, Clone, Eq, PartialEq)]
149pub struct PolyTraitRef {
150 /// The `'a` in `<'a> Foo<&'a T>`
151 pub bound_lifetimes: Vec<LifetimeDef>,
152 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
153 pub trait_ref: Path,
154}
155
156/// The explicit Self type in a "qualified path". The actual
157/// path, including the trait and the associated item, is stored
158/// separately. `position` represents the index of the associated
159/// item qualified with this Self type.
160///
161/// ```rust,ignore
162/// <Vec<T> as a::b::Trait>::AssociatedItem
163/// ^~~~~ ~~~~~~~~~~~~~~^
164/// ty position = 3
165///
166/// <Vec<T>>::AssociatedItem
167/// ^~~~~ ^
168/// ty position = 0
169/// ```
170#[derive(Debug, Clone, Eq, PartialEq)]
171pub struct QSelf {
172 pub ty: Box<Ty>,
David Tolnaydaaf7742016-10-03 11:11:43 -0700173 pub position: usize,
David Tolnayb79ee962016-09-04 09:39:20 -0700174}
175
176#[derive(Debug, Clone, Eq, PartialEq)]
177pub struct BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700178 pub unsafety: Unsafety,
179 pub abi: Option<Abi>,
David Tolnayb79ee962016-09-04 09:39:20 -0700180 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700181 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700182 pub output: FunctionRetTy,
David Tolnay292e6002016-10-29 22:03:51 -0700183 pub variadic: bool,
David Tolnayb79ee962016-09-04 09:39:20 -0700184}
185
David Tolnayb8d8ef52016-10-29 14:30:08 -0700186#[derive(Debug, Copy, Clone, Eq, PartialEq)]
187pub enum Unsafety {
188 Unsafe,
189 Normal,
190}
191
192#[derive(Debug, Clone, Eq, PartialEq)]
193pub enum Abi {
194 Named(String),
195 Extern,
196}
197
David Tolnay62f374c2016-10-02 13:37:00 -0700198/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700199///
200/// E.g. `bar: usize` as in `fn foo(bar: usize)`
201#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay62f374c2016-10-02 13:37:00 -0700202pub struct BareFnArg {
203 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700204 pub ty: Ty,
205}
206
207#[derive(Debug, Clone, Eq, PartialEq)]
208pub enum FunctionRetTy {
209 /// Return type is not specified.
210 ///
211 /// Functions default to `()` and
212 /// closures default to inference. Span points to where return
213 /// type would be inserted.
214 Default,
215 /// Everything else
216 Ty(Ty),
217}
218
David Tolnay86eca752016-09-04 11:26:41 -0700219#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700220pub mod parsing {
221 use super::*;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700222 #[cfg(feature = "full")]
223 use ConstExpr;
David Tolnay3cb23a92016-10-07 23:02:21 -0700224 use constant::parsing::const_expr;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700225 #[cfg(feature = "full")]
226 use expr::parsing::expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700227 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700228 use ident::parsing::ident;
David Tolnayb8d8ef52016-10-29 14:30:08 -0700229 use lit::parsing::quoted_string;
David Tolnay9d8f1972016-09-04 11:58:48 -0700230 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700231
David Tolnayb5a7b142016-09-13 22:46:39 -0700232 named!(pub ty -> Ty, alt!(
David Tolnayd040d772016-10-25 21:33:51 -0700233 ty_paren // must be before ty_tup
234 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700235 ty_path // must be before ty_poly_trait_ref
236 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700237 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700238 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700239 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700240 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700241 ty_ptr
242 |
243 ty_rptr
244 |
245 ty_bare_fn
246 |
247 ty_never
248 |
249 ty_tup
250 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700251 ty_poly_trait_ref
David Tolnay9d8f1972016-09-04 11:58:48 -0700252 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700253 ty_impl_trait
David Tolnay9d8f1972016-09-04 11:58:48 -0700254 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700255
David Tolnayb5a7b142016-09-13 22:46:39 -0700256 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700257 punct!("[") >>
258 elem: ty >>
259 punct!("]") >>
David Tolnay16709ba2016-10-05 23:11:32 -0700260 (Ty::Slice(Box::new(elem)))
David Tolnay9d8f1972016-09-04 11:58:48 -0700261 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700262
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700263 #[cfg(not(feature = "full"))]
David Tolnayfa94b6f2016-10-05 23:26:11 -0700264 named!(ty_array -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700265 punct!("[") >>
266 elem: ty >>
267 punct!(";") >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700268 len: const_expr >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700269 punct!("]") >>
David Tolnayfa94b6f2016-10-05 23:26:11 -0700270 (Ty::Array(Box::new(elem), len))
271 ));
272
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700273 #[cfg(feature = "full")]
274 named!(ty_array -> Ty, do_parse!(
275 punct!("[") >>
276 elem: ty >>
277 punct!(";") >>
278 len: alt!(
279 terminated!(const_expr, punct!("]"))
280 |
281 terminated!(expr, punct!("]")) => { ConstExpr::Other }
282 ) >>
283 (Ty::Array(Box::new(elem), len))
284 ));
285
David Tolnayb5a7b142016-09-13 22:46:39 -0700286 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700287 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700288 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700289 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700290 |
David Tolnay10413f02016-09-30 09:12:02 -0700291 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700292 ) >>
293 target: ty >>
294 (Ty::Ptr(Box::new(MutTy {
295 ty: target,
296 mutability: mutability,
297 })))
298 ));
299
David Tolnayb5a7b142016-09-13 22:46:39 -0700300 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700301 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700302 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700303 mutability: mutability >>
304 target: ty >>
305 (Ty::Rptr(life, Box::new(MutTy {
306 ty: target,
307 mutability: mutability,
308 })))
309 ));
310
David Tolnayb5a7b142016-09-13 22:46:39 -0700311 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay4f121832016-10-25 21:33:36 -0700312 lifetimes: opt_vec!(do_parse!(
313 keyword!("for") >>
314 punct!("<") >>
315 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
316 punct!(">") >>
317 (lifetimes)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700318 )) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700319 unsafety: unsafety >>
320 abi: option!(abi) >>
David Tolnay4f121832016-10-25 21:33:36 -0700321 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700322 punct!("(") >>
David Tolnay292e6002016-10-29 22:03:51 -0700323 inputs: separated_list!(punct!(","), fn_arg) >>
324 trailing_comma: option!(punct!(",")) >>
325 variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700326 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700327 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700328 punct!("->"),
329 ty
330 )) >>
331 (Ty::BareFn(Box::new(BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700332 unsafety: unsafety,
333 abi: abi,
David Tolnay9d8f1972016-09-04 11:58:48 -0700334 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700335 inputs: inputs,
336 output: match output {
337 Some(ty) => FunctionRetTy::Ty(ty),
338 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700339 },
David Tolnay292e6002016-10-29 22:03:51 -0700340 variadic: variadic.is_some(),
David Tolnay9d8f1972016-09-04 11:58:48 -0700341 })))
342 ));
343
David Tolnayb5a7b142016-09-13 22:46:39 -0700344 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700345
David Tolnayb5a7b142016-09-13 22:46:39 -0700346 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700347 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700348 elems: terminated_list!(punct!(","), ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700349 punct!(")") >>
350 (Ty::Tup(elems))
351 ));
352
David Tolnay6414da72016-10-08 00:55:17 -0700353 named!(ty_path -> Ty, do_parse!(
354 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700355 parenthesized: cond!(
356 qpath.1.segments.last().unwrap().parameters == PathParameters::none(),
357 option!(parenthesized_parameter_data)
358 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700359 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
360 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700361 let (qself, mut path) = qpath;
362 if let Some(Some(parenthesized)) = parenthesized {
363 path.segments.last_mut().unwrap().parameters = parenthesized;
364 }
365 let path = Ty::Path(qself, path);
David Tolnay6414da72016-10-08 00:55:17 -0700366 if bounds.is_empty() {
367 path
368 } else {
369 Ty::ObjectSum(Box::new(path), bounds)
370 }
371 })
372 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700373
David Tolnayf6c74402016-10-08 02:31:26 -0700374 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
375 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700376 inputs: terminated_list!(punct!(","), ty) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700377 punct!(")") >>
378 output: option!(preceded!(
379 punct!("->"),
380 ty
381 )) >>
382 (PathParameters::Parenthesized(
383 ParenthesizedParameterData {
384 inputs: inputs,
385 output: output,
386 },
387 ))
388 ));
389
David Tolnay9636c052016-10-02 17:11:17 -0700390 named!(pub qpath -> (Option<QSelf>, Path), alt!(
391 map!(path, |p| (None, p))
392 |
393 do_parse!(
394 punct!("<") >>
395 this: map!(ty, Box::new) >>
396 path: option!(preceded!(
397 keyword!("as"),
398 path
399 )) >>
400 punct!(">") >>
401 punct!("::") >>
402 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
403 ({
404 match path {
405 Some(mut path) => {
406 let pos = path.segments.len();
407 path.segments.extend(rest);
408 (Some(QSelf { ty: this, position: pos }), path)
409 }
410 None => {
411 (Some(QSelf { ty: this, position: 0 }), Path {
412 global: false,
413 segments: rest,
414 })
415 }
David Tolnayb79ee962016-09-04 09:39:20 -0700416 }
David Tolnay9636c052016-10-02 17:11:17 -0700417 })
418 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700419 |
420 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700421 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700422
David Tolnay4f0f2512016-10-30 09:28:14 -0700423 named!(ty_poly_trait_ref -> Ty, map!(
David Tolnay8eb6c452016-10-30 13:19:15 -0700424 separated_nonempty_list!(punct!("+"), ty_param_bound),
425 Ty::PolyTraitRef
David Tolnay6414da72016-10-08 00:55:17 -0700426 ));
427
David Tolnayb5a7b142016-09-13 22:46:39 -0700428 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700429 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700430 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
431 (Ty::ImplTrait(elem))
432 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700433
David Tolnayb5a7b142016-09-13 22:46:39 -0700434 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700435 punct!("(") >>
436 elem: ty >>
437 punct!(")") >>
438 (Ty::Paren(Box::new(elem)))
439 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700440
David Tolnay47a877c2016-10-01 16:50:55 -0700441 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700442 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700443 |
444 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700445 ));
446
David Tolnayb5a7b142016-09-13 22:46:39 -0700447 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700448 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700449 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
450 (Path {
451 global: global.is_some(),
452 segments: segments,
453 })
454 ));
455
David Tolnay9636c052016-10-02 17:11:17 -0700456 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700457 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700458 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700459 punct!("<") >>
460 lifetimes: separated_list!(punct!(","), lifetime) >>
461 types: opt_vec!(preceded!(
462 cond!(!lifetimes.is_empty(), punct!(",")),
463 separated_nonempty_list!(
464 punct!(","),
465 terminated!(ty, not!(peek!(punct!("="))))
466 )
467 )) >>
468 bindings: opt_vec!(preceded!(
469 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
470 separated_nonempty_list!(punct!(","), type_binding)
471 )) >>
David Tolnay82a47d52016-10-30 13:01:38 -0700472 cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700473 punct!(">") >>
474 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700475 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700476 parameters: PathParameters::AngleBracketed(
477 AngleBracketedParameterData {
478 lifetimes: lifetimes,
479 types: types,
480 bindings: bindings,
481 }
482 ),
483 })
484 )
485 |
David Tolnay84aa0752016-10-02 23:01:13 -0700486 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700487 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700488 map!(alt!(
489 keyword!("super")
490 |
491 keyword!("self")
492 |
493 keyword!("Self")
494 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700495 ));
496
David Tolnayb5a7b142016-09-13 22:46:39 -0700497 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700498 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700499 punct!("=") >>
500 ty: ty >>
501 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700502 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700503 ty: ty,
504 })
505 ));
506
David Tolnayb5a7b142016-09-13 22:46:39 -0700507 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700508 bound_lifetimes: bound_lifetimes >>
509 trait_ref: path >>
David Tolnay4f0f2512016-10-30 09:28:14 -0700510 parenthesized: option!(cond_reduce!(
David Tolnayf6c74402016-10-08 02:31:26 -0700511 trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
David Tolnay4f0f2512016-10-30 09:28:14 -0700512 parenthesized_parameter_data
513 )) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700514 ({
515 let mut trait_ref = trait_ref;
David Tolnay4f0f2512016-10-30 09:28:14 -0700516 if let Some(parenthesized) = parenthesized {
David Tolnayf6c74402016-10-08 02:31:26 -0700517 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
518 }
519 PolyTraitRef {
520 bound_lifetimes: bound_lifetimes,
521 trait_ref: trait_ref,
522 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700523 })
524 ));
525
David Tolnay62f374c2016-10-02 13:37:00 -0700526 named!(pub fn_arg -> BareFnArg, do_parse!(
David Tolnayb0417d72016-10-25 21:46:35 -0700527 name: option!(do_parse!(
528 name: ident >>
529 punct!(":") >>
530 not!(peek!(tag!(":"))) >> // not ::
531 (name)
532 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700533 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700534 (BareFnArg {
535 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700536 ty: ty,
537 })
538 ));
David Tolnayb8d8ef52016-10-29 14:30:08 -0700539
540 named!(pub unsafety -> Unsafety, alt!(
541 keyword!("unsafe") => { |_| Unsafety::Unsafe }
542 |
543 epsilon!() => { |_| Unsafety::Normal }
544 ));
545
546 named!(pub abi -> Abi, do_parse!(
547 keyword!("extern") >>
548 name: option!(quoted_string) >>
549 (match name {
550 Some(name) => Abi::Named(name),
551 None => Abi::Extern,
552 })
553 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700554}
David Tolnay87d0b442016-09-04 11:52:12 -0700555
556#[cfg(feature = "printing")]
557mod printing {
558 use super::*;
559 use quote::{Tokens, ToTokens};
560
561 impl ToTokens for Ty {
562 fn to_tokens(&self, tokens: &mut Tokens) {
563 match *self {
David Tolnay16709ba2016-10-05 23:11:32 -0700564 Ty::Slice(ref inner) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700565 tokens.append("[");
566 inner.to_tokens(tokens);
567 tokens.append("]");
568 }
David Tolnayfa94b6f2016-10-05 23:26:11 -0700569 Ty::Array(ref inner, ref len) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700570 tokens.append("[");
571 inner.to_tokens(tokens);
572 tokens.append(";");
David Tolnayfa94b6f2016-10-05 23:26:11 -0700573 len.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700574 tokens.append("]");
575 }
576 Ty::Ptr(ref target) => {
577 tokens.append("*");
578 match target.mutability {
579 Mutability::Mutable => tokens.append("mut"),
580 Mutability::Immutable => tokens.append("const"),
581 }
582 target.ty.to_tokens(tokens);
583 }
584 Ty::Rptr(ref lifetime, ref target) => {
585 tokens.append("&");
586 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700587 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700588 target.ty.to_tokens(tokens);
589 }
590 Ty::BareFn(ref func) => {
591 func.to_tokens(tokens);
592 }
593 Ty::Never => {
594 tokens.append("!");
595 }
596 Ty::Tup(ref elems) => {
597 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700598 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700599 if elems.len() == 1 {
600 tokens.append(",");
601 }
602 tokens.append(")");
603 }
David Tolnayf69904a2016-09-04 14:46:07 -0700604 Ty::Path(None, ref path) => {
605 path.to_tokens(tokens);
606 }
607 Ty::Path(Some(ref qself), ref path) => {
608 tokens.append("<");
609 qself.ty.to_tokens(tokens);
610 if qself.position > 0 {
611 tokens.append("as");
David Tolnaydaaf7742016-10-03 11:11:43 -0700612 for (i, segment) in path.segments
613 .iter()
614 .take(qself.position)
615 .enumerate() {
David Tolnayf69904a2016-09-04 14:46:07 -0700616 if i > 0 || path.global {
617 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700618 }
David Tolnayf69904a2016-09-04 14:46:07 -0700619 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700620 }
David Tolnayf69904a2016-09-04 14:46:07 -0700621 }
622 tokens.append(">");
623 for segment in path.segments.iter().skip(qself.position) {
624 tokens.append("::");
625 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700626 }
627 }
David Tolnay6414da72016-10-08 00:55:17 -0700628 Ty::ObjectSum(ref ty, ref bounds) => {
629 ty.to_tokens(tokens);
630 for bound in bounds {
631 tokens.append("+");
632 bound.to_tokens(tokens);
633 }
634 }
635 Ty::PolyTraitRef(ref bounds) => {
636 tokens.append_separated(bounds, "+");
637 }
David Tolnay87d0b442016-09-04 11:52:12 -0700638 Ty::ImplTrait(ref bounds) => {
639 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700640 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700641 }
642 Ty::Paren(ref inner) => {
643 tokens.append("(");
644 inner.to_tokens(tokens);
645 tokens.append(")");
646 }
647 Ty::Infer => {
648 tokens.append("_");
649 }
650 }
651 }
652 }
653
David Tolnay47a877c2016-10-01 16:50:55 -0700654 impl ToTokens for Mutability {
655 fn to_tokens(&self, tokens: &mut Tokens) {
656 if let Mutability::Mutable = *self {
657 tokens.append("mut");
658 }
659 }
660 }
661
David Tolnay87d0b442016-09-04 11:52:12 -0700662 impl ToTokens for Path {
663 fn to_tokens(&self, tokens: &mut Tokens) {
664 for (i, segment) in self.segments.iter().enumerate() {
665 if i > 0 || self.global {
666 tokens.append("::");
667 }
668 segment.to_tokens(tokens);
669 }
670 }
671 }
672
673 impl ToTokens for PathSegment {
674 fn to_tokens(&self, tokens: &mut Tokens) {
675 self.ident.to_tokens(tokens);
David Tolnay5332d4b2016-10-30 14:25:22 -0700676 if self.ident.as_ref().is_empty() && self.parameters.is_empty() {
677 tokens.append("<");
678 tokens.append(">");
679 } else {
680 self.parameters.to_tokens(tokens);
681 }
David Tolnay87d0b442016-09-04 11:52:12 -0700682 }
683 }
684
685 impl ToTokens for PathParameters {
686 fn to_tokens(&self, tokens: &mut Tokens) {
687 match *self {
688 PathParameters::AngleBracketed(ref parameters) => {
689 parameters.to_tokens(tokens);
690 }
691 PathParameters::Parenthesized(ref parameters) => {
692 parameters.to_tokens(tokens);
693 }
694 }
695 }
696 }
697
698 impl ToTokens for AngleBracketedParameterData {
699 fn to_tokens(&self, tokens: &mut Tokens) {
700 let has_lifetimes = !self.lifetimes.is_empty();
701 let has_types = !self.types.is_empty();
702 let has_bindings = !self.bindings.is_empty();
703 if !has_lifetimes && !has_types && !has_bindings {
704 return;
705 }
706
707 tokens.append("<");
708
709 let mut first = true;
710 for lifetime in &self.lifetimes {
711 if !first {
712 tokens.append(",");
713 }
714 lifetime.to_tokens(tokens);
715 first = false;
716 }
717 for ty in &self.types {
718 if !first {
719 tokens.append(",");
720 }
721 ty.to_tokens(tokens);
722 first = false;
723 }
724 for binding in &self.bindings {
725 if !first {
726 tokens.append(",");
727 }
728 binding.to_tokens(tokens);
729 first = false;
730 }
731
732 tokens.append(">");
733 }
734 }
735
736 impl ToTokens for TypeBinding {
737 fn to_tokens(&self, tokens: &mut Tokens) {
738 self.ident.to_tokens(tokens);
739 tokens.append("=");
740 self.ty.to_tokens(tokens);
741 }
742 }
743
744 impl ToTokens for ParenthesizedParameterData {
745 fn to_tokens(&self, tokens: &mut Tokens) {
746 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700747 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700748 tokens.append(")");
749 if let Some(ref output) = self.output {
750 tokens.append("->");
751 output.to_tokens(tokens);
752 }
753 }
754 }
755
756 impl ToTokens for PolyTraitRef {
757 fn to_tokens(&self, tokens: &mut Tokens) {
758 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700759 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700760 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700761 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700762 tokens.append(">");
763 }
764 self.trait_ref.to_tokens(tokens);
765 }
766 }
767
768 impl ToTokens for BareFnTy {
769 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay87d0b442016-09-04 11:52:12 -0700770 if !self.lifetimes.is_empty() {
David Tolnay4f121832016-10-25 21:33:36 -0700771 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700772 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700773 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700774 tokens.append(">");
775 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700776 self.unsafety.to_tokens(tokens);
777 self.abi.to_tokens(tokens);
David Tolnay4f121832016-10-25 21:33:36 -0700778 tokens.append("fn");
David Tolnay87d0b442016-09-04 11:52:12 -0700779 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700780 tokens.append_separated(&self.inputs, ",");
David Tolnay292e6002016-10-29 22:03:51 -0700781 if self.variadic {
782 if !self.inputs.is_empty() {
783 tokens.append(",");
784 }
785 tokens.append("...");
786 }
David Tolnay87d0b442016-09-04 11:52:12 -0700787 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700788 if let FunctionRetTy::Ty(ref ty) = self.output {
789 tokens.append("->");
790 ty.to_tokens(tokens);
791 }
792 }
793 }
794
David Tolnay62f374c2016-10-02 13:37:00 -0700795 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700796 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700797 if let Some(ref name) = self.name {
798 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700799 tokens.append(":");
800 }
801 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700802 }
803 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700804
805 impl ToTokens for Unsafety {
806 fn to_tokens(&self, tokens: &mut Tokens) {
807 match *self {
808 Unsafety::Unsafe => tokens.append("unsafe"),
809 Unsafety::Normal => {
810 // nothing
811 }
812 }
813 }
814 }
815
816 impl ToTokens for Abi {
817 fn to_tokens(&self, tokens: &mut Tokens) {
818 tokens.append("extern");
819 match *self {
820 Abi::Named(ref named) => named.to_tokens(tokens),
821 Abi::Extern => {}
822 }
823 }
824 }
David Tolnay87d0b442016-09-04 11:52:12 -0700825}