blob: 48cf0f944ffb22250851aaa8ead5953b4781c083 [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) => {
David Tolnayc1fea502016-10-30 17:54:02 -0700112 bracketed.lifetimes.is_empty() && bracketed.types.is_empty() &&
113 bracketed.bindings.is_empty()
David Tolnay5332d4b2016-10-30 14:25:22 -0700114 }
115 PathParameters::Parenthesized(_) => false,
116 }
117 }
David Tolnayb79ee962016-09-04 09:39:20 -0700118}
119
120/// A path like `Foo<'a, T>`
121#[derive(Debug, Clone, Eq, PartialEq, Default)]
122pub struct AngleBracketedParameterData {
123 /// The lifetime parameters for this path segment.
124 pub lifetimes: Vec<Lifetime>,
125 /// The type parameters for this path segment, if present.
126 pub types: Vec<Ty>,
127 /// Bindings (equality constraints) on associated types, if present.
128 ///
129 /// E.g., `Foo<A=Bar>`.
130 pub bindings: Vec<TypeBinding>,
131}
132
133/// Bind a type to an associated type: `A=Foo`.
134#[derive(Debug, Clone, Eq, PartialEq)]
135pub struct TypeBinding {
136 pub ident: Ident,
137 pub ty: Ty,
138}
139
140/// A path like `Foo(A,B) -> C`
141#[derive(Debug, Clone, Eq, PartialEq)]
142pub struct ParenthesizedParameterData {
143 /// `(A, B)`
144 pub inputs: Vec<Ty>,
145 /// `C`
146 pub output: Option<Ty>,
147}
148
149#[derive(Debug, Clone, Eq, PartialEq)]
150pub struct PolyTraitRef {
151 /// The `'a` in `<'a> Foo<&'a T>`
152 pub bound_lifetimes: Vec<LifetimeDef>,
153 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
154 pub trait_ref: Path,
155}
156
157/// The explicit Self type in a "qualified path". The actual
158/// path, including the trait and the associated item, is stored
159/// separately. `position` represents the index of the associated
160/// item qualified with this Self type.
161///
162/// ```rust,ignore
163/// <Vec<T> as a::b::Trait>::AssociatedItem
164/// ^~~~~ ~~~~~~~~~~~~~~^
165/// ty position = 3
166///
167/// <Vec<T>>::AssociatedItem
168/// ^~~~~ ^
169/// ty position = 0
170/// ```
171#[derive(Debug, Clone, Eq, PartialEq)]
172pub struct QSelf {
173 pub ty: Box<Ty>,
David Tolnaydaaf7742016-10-03 11:11:43 -0700174 pub position: usize,
David Tolnayb79ee962016-09-04 09:39:20 -0700175}
176
177#[derive(Debug, Clone, Eq, PartialEq)]
178pub struct BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700179 pub unsafety: Unsafety,
180 pub abi: Option<Abi>,
David Tolnayb79ee962016-09-04 09:39:20 -0700181 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700182 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700183 pub output: FunctionRetTy,
David Tolnay292e6002016-10-29 22:03:51 -0700184 pub variadic: bool,
David Tolnayb79ee962016-09-04 09:39:20 -0700185}
186
David Tolnayb8d8ef52016-10-29 14:30:08 -0700187#[derive(Debug, Copy, Clone, Eq, PartialEq)]
188pub enum Unsafety {
189 Unsafe,
190 Normal,
191}
192
193#[derive(Debug, Clone, Eq, PartialEq)]
194pub enum Abi {
195 Named(String),
David Tolnay76195ce2016-10-30 16:53:48 -0700196 Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700197}
198
David Tolnay62f374c2016-10-02 13:37:00 -0700199/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700200///
201/// E.g. `bar: usize` as in `fn foo(bar: usize)`
202#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay62f374c2016-10-02 13:37:00 -0700203pub struct BareFnArg {
204 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700205 pub ty: Ty,
206}
207
208#[derive(Debug, Clone, Eq, PartialEq)]
209pub enum FunctionRetTy {
210 /// Return type is not specified.
211 ///
212 /// Functions default to `()` and
213 /// closures default to inference. Span points to where return
214 /// type would be inserted.
215 Default,
216 /// Everything else
217 Ty(Ty),
218}
219
David Tolnay86eca752016-09-04 11:26:41 -0700220#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700221pub mod parsing {
222 use super::*;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700223 #[cfg(feature = "full")]
224 use ConstExpr;
David Tolnay3cb23a92016-10-07 23:02:21 -0700225 use constant::parsing::const_expr;
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700226 #[cfg(feature = "full")]
227 use expr::parsing::expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700228 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700229 use ident::parsing::ident;
David Tolnayb8d8ef52016-10-29 14:30:08 -0700230 use lit::parsing::quoted_string;
David Tolnay9d8f1972016-09-04 11:58:48 -0700231 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700232
David Tolnayb5a7b142016-09-13 22:46:39 -0700233 named!(pub ty -> Ty, alt!(
David Tolnayd040d772016-10-25 21:33:51 -0700234 ty_paren // must be before ty_tup
235 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700236 ty_path // must be before ty_poly_trait_ref
237 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700238 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700239 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700240 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700241 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700242 ty_ptr
243 |
244 ty_rptr
245 |
246 ty_bare_fn
247 |
248 ty_never
249 |
250 ty_tup
251 |
David Tolnay4f0f2512016-10-30 09:28:14 -0700252 ty_poly_trait_ref
David Tolnay9d8f1972016-09-04 11:58:48 -0700253 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700254 ty_impl_trait
David Tolnay9d8f1972016-09-04 11:58:48 -0700255 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700256
David Tolnayb5a7b142016-09-13 22:46:39 -0700257 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700258 punct!("[") >>
259 elem: ty >>
260 punct!("]") >>
David Tolnay16709ba2016-10-05 23:11:32 -0700261 (Ty::Slice(Box::new(elem)))
David Tolnay9d8f1972016-09-04 11:58:48 -0700262 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700263
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700264 #[cfg(not(feature = "full"))]
David Tolnayfa94b6f2016-10-05 23:26:11 -0700265 named!(ty_array -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700266 punct!("[") >>
267 elem: ty >>
268 punct!(";") >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700269 len: const_expr >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700270 punct!("]") >>
David Tolnayfa94b6f2016-10-05 23:26:11 -0700271 (Ty::Array(Box::new(elem), len))
272 ));
273
David Tolnayfe2cc9a2016-10-30 12:47:36 -0700274 #[cfg(feature = "full")]
275 named!(ty_array -> Ty, do_parse!(
276 punct!("[") >>
277 elem: ty >>
278 punct!(";") >>
279 len: alt!(
280 terminated!(const_expr, punct!("]"))
281 |
282 terminated!(expr, punct!("]")) => { ConstExpr::Other }
283 ) >>
284 (Ty::Array(Box::new(elem), len))
285 ));
286
David Tolnayb5a7b142016-09-13 22:46:39 -0700287 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700288 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700289 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700290 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700291 |
David Tolnay10413f02016-09-30 09:12:02 -0700292 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700293 ) >>
294 target: ty >>
295 (Ty::Ptr(Box::new(MutTy {
296 ty: target,
297 mutability: mutability,
298 })))
299 ));
300
David Tolnayb5a7b142016-09-13 22:46:39 -0700301 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700302 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700303 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700304 mutability: mutability >>
305 target: ty >>
306 (Ty::Rptr(life, Box::new(MutTy {
307 ty: target,
308 mutability: mutability,
309 })))
310 ));
311
David Tolnayb5a7b142016-09-13 22:46:39 -0700312 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay4f121832016-10-25 21:33:36 -0700313 lifetimes: opt_vec!(do_parse!(
314 keyword!("for") >>
315 punct!("<") >>
316 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
317 punct!(">") >>
318 (lifetimes)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700319 )) >>
David Tolnayb8d8ef52016-10-29 14:30:08 -0700320 unsafety: unsafety >>
321 abi: option!(abi) >>
David Tolnay4f121832016-10-25 21:33:36 -0700322 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700323 punct!("(") >>
David Tolnay292e6002016-10-29 22:03:51 -0700324 inputs: separated_list!(punct!(","), fn_arg) >>
325 trailing_comma: option!(punct!(",")) >>
326 variadic: option!(cond_reduce!(trailing_comma.is_some(), punct!("..."))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700327 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700328 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700329 punct!("->"),
330 ty
331 )) >>
332 (Ty::BareFn(Box::new(BareFnTy {
David Tolnayb8d8ef52016-10-29 14:30:08 -0700333 unsafety: unsafety,
334 abi: abi,
David Tolnay9d8f1972016-09-04 11:58:48 -0700335 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700336 inputs: inputs,
337 output: match output {
338 Some(ty) => FunctionRetTy::Ty(ty),
339 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700340 },
David Tolnay292e6002016-10-29 22:03:51 -0700341 variadic: variadic.is_some(),
David Tolnay9d8f1972016-09-04 11:58:48 -0700342 })))
343 ));
344
David Tolnayb5a7b142016-09-13 22:46:39 -0700345 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700346
David Tolnayb5a7b142016-09-13 22:46:39 -0700347 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700348 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700349 elems: terminated_list!(punct!(","), ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700350 punct!(")") >>
351 (Ty::Tup(elems))
352 ));
353
David Tolnay6414da72016-10-08 00:55:17 -0700354 named!(ty_path -> Ty, do_parse!(
355 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700356 parenthesized: cond!(
357 qpath.1.segments.last().unwrap().parameters == PathParameters::none(),
358 option!(parenthesized_parameter_data)
359 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700360 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
361 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700362 let (qself, mut path) = qpath;
363 if let Some(Some(parenthesized)) = parenthesized {
364 path.segments.last_mut().unwrap().parameters = parenthesized;
365 }
366 let path = Ty::Path(qself, path);
David Tolnay6414da72016-10-08 00:55:17 -0700367 if bounds.is_empty() {
368 path
369 } else {
370 Ty::ObjectSum(Box::new(path), bounds)
371 }
372 })
373 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700374
David Tolnayf6c74402016-10-08 02:31:26 -0700375 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
376 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700377 inputs: terminated_list!(punct!(","), ty) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700378 punct!(")") >>
379 output: option!(preceded!(
380 punct!("->"),
381 ty
382 )) >>
383 (PathParameters::Parenthesized(
384 ParenthesizedParameterData {
385 inputs: inputs,
386 output: output,
387 },
388 ))
389 ));
390
David Tolnay9636c052016-10-02 17:11:17 -0700391 named!(pub qpath -> (Option<QSelf>, Path), alt!(
392 map!(path, |p| (None, p))
393 |
394 do_parse!(
395 punct!("<") >>
396 this: map!(ty, Box::new) >>
397 path: option!(preceded!(
398 keyword!("as"),
399 path
400 )) >>
401 punct!(">") >>
402 punct!("::") >>
403 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
404 ({
405 match path {
406 Some(mut path) => {
407 let pos = path.segments.len();
408 path.segments.extend(rest);
409 (Some(QSelf { ty: this, position: pos }), path)
410 }
411 None => {
412 (Some(QSelf { ty: this, position: 0 }), Path {
413 global: false,
414 segments: rest,
415 })
416 }
David Tolnayb79ee962016-09-04 09:39:20 -0700417 }
David Tolnay9636c052016-10-02 17:11:17 -0700418 })
419 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700420 |
421 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700422 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700423
David Tolnay4f0f2512016-10-30 09:28:14 -0700424 named!(ty_poly_trait_ref -> Ty, map!(
David Tolnay8eb6c452016-10-30 13:19:15 -0700425 separated_nonempty_list!(punct!("+"), ty_param_bound),
426 Ty::PolyTraitRef
David Tolnay6414da72016-10-08 00:55:17 -0700427 ));
428
David Tolnayb5a7b142016-09-13 22:46:39 -0700429 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700430 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700431 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
432 (Ty::ImplTrait(elem))
433 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700434
David Tolnayb5a7b142016-09-13 22:46:39 -0700435 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700436 punct!("(") >>
437 elem: ty >>
438 punct!(")") >>
439 (Ty::Paren(Box::new(elem)))
440 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700441
David Tolnay47a877c2016-10-01 16:50:55 -0700442 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700443 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700444 |
445 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700446 ));
447
David Tolnayb5a7b142016-09-13 22:46:39 -0700448 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700449 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700450 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
451 (Path {
452 global: global.is_some(),
453 segments: segments,
454 })
455 ));
456
David Tolnay9636c052016-10-02 17:11:17 -0700457 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700458 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700459 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700460 punct!("<") >>
461 lifetimes: separated_list!(punct!(","), lifetime) >>
462 types: opt_vec!(preceded!(
463 cond!(!lifetimes.is_empty(), punct!(",")),
464 separated_nonempty_list!(
465 punct!(","),
466 terminated!(ty, not!(peek!(punct!("="))))
467 )
468 )) >>
469 bindings: opt_vec!(preceded!(
470 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
471 separated_nonempty_list!(punct!(","), type_binding)
472 )) >>
David Tolnay82a47d52016-10-30 13:01:38 -0700473 cond!(!lifetimes.is_empty() || !types.is_empty() || !bindings.is_empty(), option!(punct!(","))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700474 punct!(">") >>
475 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700476 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700477 parameters: PathParameters::AngleBracketed(
478 AngleBracketedParameterData {
479 lifetimes: lifetimes,
480 types: types,
481 bindings: bindings,
482 }
483 ),
484 })
485 )
486 |
David Tolnay84aa0752016-10-02 23:01:13 -0700487 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700488 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700489 map!(alt!(
490 keyword!("super")
491 |
492 keyword!("self")
493 |
494 keyword!("Self")
495 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700496 ));
497
David Tolnayb5a7b142016-09-13 22:46:39 -0700498 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700499 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700500 punct!("=") >>
501 ty: ty >>
502 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700503 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700504 ty: ty,
505 })
506 ));
507
David Tolnayb5a7b142016-09-13 22:46:39 -0700508 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700509 bound_lifetimes: bound_lifetimes >>
510 trait_ref: path >>
David Tolnay4f0f2512016-10-30 09:28:14 -0700511 parenthesized: option!(cond_reduce!(
David Tolnayf6c74402016-10-08 02:31:26 -0700512 trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
David Tolnay4f0f2512016-10-30 09:28:14 -0700513 parenthesized_parameter_data
514 )) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700515 ({
516 let mut trait_ref = trait_ref;
David Tolnay4f0f2512016-10-30 09:28:14 -0700517 if let Some(parenthesized) = parenthesized {
David Tolnayf6c74402016-10-08 02:31:26 -0700518 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
519 }
520 PolyTraitRef {
521 bound_lifetimes: bound_lifetimes,
522 trait_ref: trait_ref,
523 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700524 })
525 ));
526
David Tolnay62f374c2016-10-02 13:37:00 -0700527 named!(pub fn_arg -> BareFnArg, do_parse!(
David Tolnayb0417d72016-10-25 21:46:35 -0700528 name: option!(do_parse!(
529 name: ident >>
530 punct!(":") >>
531 not!(peek!(tag!(":"))) >> // not ::
532 (name)
533 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700534 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700535 (BareFnArg {
536 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700537 ty: ty,
538 })
539 ));
David Tolnayb8d8ef52016-10-29 14:30:08 -0700540
541 named!(pub unsafety -> Unsafety, alt!(
542 keyword!("unsafe") => { |_| Unsafety::Unsafe }
543 |
544 epsilon!() => { |_| Unsafety::Normal }
545 ));
546
547 named!(pub abi -> Abi, do_parse!(
548 keyword!("extern") >>
549 name: option!(quoted_string) >>
550 (match name {
551 Some(name) => Abi::Named(name),
David Tolnay76195ce2016-10-30 16:53:48 -0700552 None => Abi::Rust,
David Tolnayb8d8ef52016-10-29 14:30:08 -0700553 })
554 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700555}
David Tolnay87d0b442016-09-04 11:52:12 -0700556
557#[cfg(feature = "printing")]
558mod printing {
559 use super::*;
560 use quote::{Tokens, ToTokens};
561
562 impl ToTokens for Ty {
563 fn to_tokens(&self, tokens: &mut Tokens) {
564 match *self {
David Tolnay16709ba2016-10-05 23:11:32 -0700565 Ty::Slice(ref inner) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700566 tokens.append("[");
567 inner.to_tokens(tokens);
568 tokens.append("]");
569 }
David Tolnayfa94b6f2016-10-05 23:26:11 -0700570 Ty::Array(ref inner, ref len) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700571 tokens.append("[");
572 inner.to_tokens(tokens);
573 tokens.append(";");
David Tolnayfa94b6f2016-10-05 23:26:11 -0700574 len.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700575 tokens.append("]");
576 }
577 Ty::Ptr(ref target) => {
578 tokens.append("*");
579 match target.mutability {
580 Mutability::Mutable => tokens.append("mut"),
581 Mutability::Immutable => tokens.append("const"),
582 }
583 target.ty.to_tokens(tokens);
584 }
585 Ty::Rptr(ref lifetime, ref target) => {
586 tokens.append("&");
587 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700588 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700589 target.ty.to_tokens(tokens);
590 }
591 Ty::BareFn(ref func) => {
592 func.to_tokens(tokens);
593 }
594 Ty::Never => {
595 tokens.append("!");
596 }
597 Ty::Tup(ref elems) => {
598 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700599 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700600 if elems.len() == 1 {
601 tokens.append(",");
602 }
603 tokens.append(")");
604 }
David Tolnayf69904a2016-09-04 14:46:07 -0700605 Ty::Path(None, ref path) => {
606 path.to_tokens(tokens);
607 }
608 Ty::Path(Some(ref qself), ref path) => {
609 tokens.append("<");
610 qself.ty.to_tokens(tokens);
611 if qself.position > 0 {
612 tokens.append("as");
David Tolnaydaaf7742016-10-03 11:11:43 -0700613 for (i, segment) in path.segments
614 .iter()
615 .take(qself.position)
616 .enumerate() {
David Tolnayf69904a2016-09-04 14:46:07 -0700617 if i > 0 || path.global {
618 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700619 }
David Tolnayf69904a2016-09-04 14:46:07 -0700620 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700621 }
David Tolnayf69904a2016-09-04 14:46:07 -0700622 }
623 tokens.append(">");
624 for segment in path.segments.iter().skip(qself.position) {
625 tokens.append("::");
626 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700627 }
628 }
David Tolnay6414da72016-10-08 00:55:17 -0700629 Ty::ObjectSum(ref ty, ref bounds) => {
630 ty.to_tokens(tokens);
631 for bound in bounds {
632 tokens.append("+");
633 bound.to_tokens(tokens);
634 }
635 }
636 Ty::PolyTraitRef(ref bounds) => {
637 tokens.append_separated(bounds, "+");
638 }
David Tolnay87d0b442016-09-04 11:52:12 -0700639 Ty::ImplTrait(ref bounds) => {
640 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700641 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700642 }
643 Ty::Paren(ref inner) => {
644 tokens.append("(");
645 inner.to_tokens(tokens);
646 tokens.append(")");
647 }
648 Ty::Infer => {
649 tokens.append("_");
650 }
651 }
652 }
653 }
654
David Tolnay47a877c2016-10-01 16:50:55 -0700655 impl ToTokens for Mutability {
656 fn to_tokens(&self, tokens: &mut Tokens) {
657 if let Mutability::Mutable = *self {
658 tokens.append("mut");
659 }
660 }
661 }
662
David Tolnay87d0b442016-09-04 11:52:12 -0700663 impl ToTokens for Path {
664 fn to_tokens(&self, tokens: &mut Tokens) {
665 for (i, segment) in self.segments.iter().enumerate() {
666 if i > 0 || self.global {
667 tokens.append("::");
668 }
669 segment.to_tokens(tokens);
670 }
671 }
672 }
673
674 impl ToTokens for PathSegment {
675 fn to_tokens(&self, tokens: &mut Tokens) {
676 self.ident.to_tokens(tokens);
David Tolnay5332d4b2016-10-30 14:25:22 -0700677 if self.ident.as_ref().is_empty() && self.parameters.is_empty() {
678 tokens.append("<");
679 tokens.append(">");
680 } else {
681 self.parameters.to_tokens(tokens);
682 }
David Tolnay87d0b442016-09-04 11:52:12 -0700683 }
684 }
685
686 impl ToTokens for PathParameters {
687 fn to_tokens(&self, tokens: &mut Tokens) {
688 match *self {
689 PathParameters::AngleBracketed(ref parameters) => {
690 parameters.to_tokens(tokens);
691 }
692 PathParameters::Parenthesized(ref parameters) => {
693 parameters.to_tokens(tokens);
694 }
695 }
696 }
697 }
698
699 impl ToTokens for AngleBracketedParameterData {
700 fn to_tokens(&self, tokens: &mut Tokens) {
701 let has_lifetimes = !self.lifetimes.is_empty();
702 let has_types = !self.types.is_empty();
703 let has_bindings = !self.bindings.is_empty();
704 if !has_lifetimes && !has_types && !has_bindings {
705 return;
706 }
707
708 tokens.append("<");
709
710 let mut first = true;
711 for lifetime in &self.lifetimes {
712 if !first {
713 tokens.append(",");
714 }
715 lifetime.to_tokens(tokens);
716 first = false;
717 }
718 for ty in &self.types {
719 if !first {
720 tokens.append(",");
721 }
722 ty.to_tokens(tokens);
723 first = false;
724 }
725 for binding in &self.bindings {
726 if !first {
727 tokens.append(",");
728 }
729 binding.to_tokens(tokens);
730 first = false;
731 }
732
733 tokens.append(">");
734 }
735 }
736
737 impl ToTokens for TypeBinding {
738 fn to_tokens(&self, tokens: &mut Tokens) {
739 self.ident.to_tokens(tokens);
740 tokens.append("=");
741 self.ty.to_tokens(tokens);
742 }
743 }
744
745 impl ToTokens for ParenthesizedParameterData {
746 fn to_tokens(&self, tokens: &mut Tokens) {
747 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700748 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700749 tokens.append(")");
750 if let Some(ref output) = self.output {
751 tokens.append("->");
752 output.to_tokens(tokens);
753 }
754 }
755 }
756
757 impl ToTokens for PolyTraitRef {
758 fn to_tokens(&self, tokens: &mut Tokens) {
759 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700760 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700761 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700762 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700763 tokens.append(">");
764 }
765 self.trait_ref.to_tokens(tokens);
766 }
767 }
768
769 impl ToTokens for BareFnTy {
770 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay87d0b442016-09-04 11:52:12 -0700771 if !self.lifetimes.is_empty() {
David Tolnay4f121832016-10-25 21:33:36 -0700772 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700773 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700774 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700775 tokens.append(">");
776 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700777 self.unsafety.to_tokens(tokens);
778 self.abi.to_tokens(tokens);
David Tolnay4f121832016-10-25 21:33:36 -0700779 tokens.append("fn");
David Tolnay87d0b442016-09-04 11:52:12 -0700780 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700781 tokens.append_separated(&self.inputs, ",");
David Tolnay292e6002016-10-29 22:03:51 -0700782 if self.variadic {
783 if !self.inputs.is_empty() {
784 tokens.append(",");
785 }
786 tokens.append("...");
787 }
David Tolnay87d0b442016-09-04 11:52:12 -0700788 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700789 if let FunctionRetTy::Ty(ref ty) = self.output {
790 tokens.append("->");
791 ty.to_tokens(tokens);
792 }
793 }
794 }
795
David Tolnay62f374c2016-10-02 13:37:00 -0700796 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700797 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700798 if let Some(ref name) = self.name {
799 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700800 tokens.append(":");
801 }
802 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700803 }
804 }
David Tolnayb8d8ef52016-10-29 14:30:08 -0700805
806 impl ToTokens for Unsafety {
807 fn to_tokens(&self, tokens: &mut Tokens) {
808 match *self {
809 Unsafety::Unsafe => tokens.append("unsafe"),
810 Unsafety::Normal => {
811 // nothing
812 }
813 }
814 }
815 }
816
817 impl ToTokens for Abi {
818 fn to_tokens(&self, tokens: &mut Tokens) {
819 tokens.append("extern");
820 match *self {
821 Abi::Named(ref named) => named.to_tokens(tokens),
David Tolnay76195ce2016-10-30 16:53:48 -0700822 Abi::Rust => {}
David Tolnayb8d8ef52016-10-29 14:30:08 -0700823 }
824 }
825 }
David Tolnay87d0b442016-09-04 11:52:12 -0700826}