blob: c4f83efa8fd1d835e96b1d80814bd9e034fa4928 [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 {
169 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700170 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700171 pub output: FunctionRetTy,
172}
173
David Tolnay62f374c2016-10-02 13:37:00 -0700174/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700175///
176/// E.g. `bar: usize` as in `fn foo(bar: usize)`
177#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay62f374c2016-10-02 13:37:00 -0700178pub struct BareFnArg {
179 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700180 pub ty: Ty,
181}
182
183#[derive(Debug, Clone, Eq, PartialEq)]
184pub enum FunctionRetTy {
185 /// Return type is not specified.
186 ///
187 /// Functions default to `()` and
188 /// closures default to inference. Span points to where return
189 /// type would be inserted.
190 Default,
191 /// Everything else
192 Ty(Ty),
193}
194
David Tolnay86eca752016-09-04 11:26:41 -0700195#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700196pub mod parsing {
197 use super::*;
David Tolnay6414da72016-10-08 00:55:17 -0700198 use {TraitBoundModifier, TyParamBound};
David Tolnay3cb23a92016-10-07 23:02:21 -0700199 use constant::parsing::const_expr;
David Tolnay9d8f1972016-09-04 11:58:48 -0700200 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700201 use ident::parsing::ident;
David Tolnay9d8f1972016-09-04 11:58:48 -0700202 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700203
David Tolnayb5a7b142016-09-13 22:46:39 -0700204 named!(pub ty -> Ty, alt!(
David Tolnay6414da72016-10-08 00:55:17 -0700205 ty_poly_trait_ref // must be before ty_path
206 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700207 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700208 |
David Tolnayfa94b6f2016-10-05 23:26:11 -0700209 ty_array
David Tolnayb79ee962016-09-04 09:39:20 -0700210 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700211 ty_ptr
212 |
213 ty_rptr
214 |
215 ty_bare_fn
216 |
217 ty_never
218 |
219 ty_tup
220 |
221 ty_path
222 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700223 ty_impl_trait
224 |
225 ty_paren
226 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700227
David Tolnayb5a7b142016-09-13 22:46:39 -0700228 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700229 punct!("[") >>
230 elem: ty >>
231 punct!("]") >>
David Tolnay16709ba2016-10-05 23:11:32 -0700232 (Ty::Slice(Box::new(elem)))
David Tolnay9d8f1972016-09-04 11:58:48 -0700233 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700234
David Tolnayfa94b6f2016-10-05 23:26:11 -0700235 named!(ty_array -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700236 punct!("[") >>
237 elem: ty >>
238 punct!(";") >>
David Tolnay3cb23a92016-10-07 23:02:21 -0700239 len: const_expr >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700240 punct!("]") >>
David Tolnayfa94b6f2016-10-05 23:26:11 -0700241 (Ty::Array(Box::new(elem), len))
242 ));
243
David Tolnayb5a7b142016-09-13 22:46:39 -0700244 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700245 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700246 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700247 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700248 |
David Tolnay10413f02016-09-30 09:12:02 -0700249 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700250 ) >>
251 target: ty >>
252 (Ty::Ptr(Box::new(MutTy {
253 ty: target,
254 mutability: mutability,
255 })))
256 ));
257
David Tolnayb5a7b142016-09-13 22:46:39 -0700258 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700259 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700260 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700261 mutability: mutability >>
262 target: ty >>
263 (Ty::Rptr(life, Box::new(MutTy {
264 ty: target,
265 mutability: mutability,
266 })))
267 ));
268
David Tolnayb5a7b142016-09-13 22:46:39 -0700269 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700270 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700271 lifetimes: opt_vec!(delimited!(
272 punct!("<"),
David Tolnayff46fd22016-10-08 13:53:28 -0700273 terminated_list!(punct!(","), lifetime_def),
David Tolnay9d8f1972016-09-04 11:58:48 -0700274 punct!(">")
David Tolnay6b7aaf02016-09-04 10:39:25 -0700275 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700276 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700277 inputs: terminated_list!(punct!(","), fn_arg) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700278 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700279 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700280 punct!("->"),
281 ty
282 )) >>
283 (Ty::BareFn(Box::new(BareFnTy {
284 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700285 inputs: inputs,
286 output: match output {
287 Some(ty) => FunctionRetTy::Ty(ty),
288 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700289 },
290 })))
291 ));
292
David Tolnayb5a7b142016-09-13 22:46:39 -0700293 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700294
David Tolnayb5a7b142016-09-13 22:46:39 -0700295 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700296 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700297 elems: terminated_list!(punct!(","), ty) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700298 punct!(")") >>
299 (Ty::Tup(elems))
300 ));
301
David Tolnay6414da72016-10-08 00:55:17 -0700302 named!(ty_path -> Ty, do_parse!(
303 qpath: qpath >>
David Tolnayf6c74402016-10-08 02:31:26 -0700304 parenthesized: cond!(
305 qpath.1.segments.last().unwrap().parameters == PathParameters::none(),
306 option!(parenthesized_parameter_data)
307 ) >>
David Tolnay6414da72016-10-08 00:55:17 -0700308 bounds: many0!(preceded!(punct!("+"), ty_param_bound)) >>
309 ({
David Tolnayf6c74402016-10-08 02:31:26 -0700310 let (qself, mut path) = qpath;
311 if let Some(Some(parenthesized)) = parenthesized {
312 path.segments.last_mut().unwrap().parameters = parenthesized;
313 }
314 let path = Ty::Path(qself, path);
David Tolnay6414da72016-10-08 00:55:17 -0700315 if bounds.is_empty() {
316 path
317 } else {
318 Ty::ObjectSum(Box::new(path), bounds)
319 }
320 })
321 ));
David Tolnay9d8f1972016-09-04 11:58:48 -0700322
David Tolnayf6c74402016-10-08 02:31:26 -0700323 named!(parenthesized_parameter_data -> PathParameters, do_parse!(
324 punct!("(") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700325 inputs: terminated_list!(punct!(","), ty) >>
David Tolnayf6c74402016-10-08 02:31:26 -0700326 punct!(")") >>
327 output: option!(preceded!(
328 punct!("->"),
329 ty
330 )) >>
331 (PathParameters::Parenthesized(
332 ParenthesizedParameterData {
333 inputs: inputs,
334 output: output,
335 },
336 ))
337 ));
338
David Tolnay9636c052016-10-02 17:11:17 -0700339 named!(pub qpath -> (Option<QSelf>, Path), alt!(
340 map!(path, |p| (None, p))
341 |
342 do_parse!(
343 punct!("<") >>
344 this: map!(ty, Box::new) >>
345 path: option!(preceded!(
346 keyword!("as"),
347 path
348 )) >>
349 punct!(">") >>
350 punct!("::") >>
351 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
352 ({
353 match path {
354 Some(mut path) => {
355 let pos = path.segments.len();
356 path.segments.extend(rest);
357 (Some(QSelf { ty: this, position: pos }), path)
358 }
359 None => {
360 (Some(QSelf { ty: this, position: 0 }), Path {
361 global: false,
362 segments: rest,
363 })
364 }
David Tolnayb79ee962016-09-04 09:39:20 -0700365 }
David Tolnay9636c052016-10-02 17:11:17 -0700366 })
367 )
David Tolnay6cd2a232016-10-24 22:41:08 -0700368 |
369 map!(keyword!("self"), |_| (None, "self".into()))
David Tolnay9d8f1972016-09-04 11:58:48 -0700370 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700371
David Tolnay6414da72016-10-08 00:55:17 -0700372 named!(ty_poly_trait_ref -> Ty, do_parse!(
373 keyword!("for") >>
374 punct!("<") >>
David Tolnayff46fd22016-10-08 13:53:28 -0700375 lifetimes: terminated_list!(punct!(","), lifetime_def) >>
David Tolnay6414da72016-10-08 00:55:17 -0700376 punct!(">") >>
377 trait_ref: path >>
378 (Ty::PolyTraitRef(vec![
379 TyParamBound::Trait(
380 PolyTraitRef {
381 bound_lifetimes: lifetimes,
382 trait_ref: trait_ref,
383 },
384 TraitBoundModifier::None,
385 ),
386 ]))
387 ));
388
David Tolnayb5a7b142016-09-13 22:46:39 -0700389 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700390 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700391 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
392 (Ty::ImplTrait(elem))
393 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700394
David Tolnayb5a7b142016-09-13 22:46:39 -0700395 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700396 punct!("(") >>
397 elem: ty >>
398 punct!(")") >>
399 (Ty::Paren(Box::new(elem)))
400 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700401
David Tolnay47a877c2016-10-01 16:50:55 -0700402 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700403 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700404 |
405 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700406 ));
407
David Tolnayb5a7b142016-09-13 22:46:39 -0700408 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700409 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700410 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
411 (Path {
412 global: global.is_some(),
413 segments: segments,
414 })
415 ));
416
David Tolnay9636c052016-10-02 17:11:17 -0700417 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700418 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700419 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700420 punct!("<") >>
421 lifetimes: separated_list!(punct!(","), lifetime) >>
422 types: opt_vec!(preceded!(
423 cond!(!lifetimes.is_empty(), punct!(",")),
424 separated_nonempty_list!(
425 punct!(","),
426 terminated!(ty, not!(peek!(punct!("="))))
427 )
428 )) >>
429 bindings: opt_vec!(preceded!(
430 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
431 separated_nonempty_list!(punct!(","), type_binding)
432 )) >>
433 punct!(">") >>
434 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700435 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700436 parameters: PathParameters::AngleBracketed(
437 AngleBracketedParameterData {
438 lifetimes: lifetimes,
439 types: types,
440 bindings: bindings,
441 }
442 ),
443 })
444 )
445 |
David Tolnay84aa0752016-10-02 23:01:13 -0700446 map!(ident, Into::into)
David Tolnay77807222016-10-24 22:30:15 -0700447 |
David Tolnaye14e3be2016-10-24 22:53:07 -0700448 map!(alt!(
449 keyword!("super")
450 |
451 keyword!("self")
452 |
453 keyword!("Self")
454 ), Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700455 ));
456
David Tolnayb5a7b142016-09-13 22:46:39 -0700457 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700458 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700459 punct!("=") >>
460 ty: ty >>
461 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700462 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700463 ty: ty,
464 })
465 ));
466
David Tolnayb5a7b142016-09-13 22:46:39 -0700467 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700468 bound_lifetimes: bound_lifetimes >>
469 trait_ref: path >>
David Tolnayf6c74402016-10-08 02:31:26 -0700470 parenthesized: cond!(
471 trait_ref.segments.last().unwrap().parameters == PathParameters::none(),
472 option!(parenthesized_parameter_data)
473 ) >>
474 ({
475 let mut trait_ref = trait_ref;
476 if let Some(Some(parenthesized)) = parenthesized {
477 trait_ref.segments.last_mut().unwrap().parameters = parenthesized;
478 }
479 PolyTraitRef {
480 bound_lifetimes: bound_lifetimes,
481 trait_ref: trait_ref,
482 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700483 })
484 ));
485
David Tolnay62f374c2016-10-02 13:37:00 -0700486 named!(pub fn_arg -> BareFnArg, do_parse!(
487 name: option!(terminated!(ident, punct!(":"))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700488 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700489 (BareFnArg {
490 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700491 ty: ty,
492 })
493 ));
494}
David Tolnay87d0b442016-09-04 11:52:12 -0700495
496#[cfg(feature = "printing")]
497mod printing {
498 use super::*;
499 use quote::{Tokens, ToTokens};
500
501 impl ToTokens for Ty {
502 fn to_tokens(&self, tokens: &mut Tokens) {
503 match *self {
David Tolnay16709ba2016-10-05 23:11:32 -0700504 Ty::Slice(ref inner) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700505 tokens.append("[");
506 inner.to_tokens(tokens);
507 tokens.append("]");
508 }
David Tolnayfa94b6f2016-10-05 23:26:11 -0700509 Ty::Array(ref inner, ref len) => {
David Tolnay87d0b442016-09-04 11:52:12 -0700510 tokens.append("[");
511 inner.to_tokens(tokens);
512 tokens.append(";");
David Tolnayfa94b6f2016-10-05 23:26:11 -0700513 len.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700514 tokens.append("]");
515 }
516 Ty::Ptr(ref target) => {
517 tokens.append("*");
518 match target.mutability {
519 Mutability::Mutable => tokens.append("mut"),
520 Mutability::Immutable => tokens.append("const"),
521 }
522 target.ty.to_tokens(tokens);
523 }
524 Ty::Rptr(ref lifetime, ref target) => {
525 tokens.append("&");
526 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700527 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700528 target.ty.to_tokens(tokens);
529 }
530 Ty::BareFn(ref func) => {
531 func.to_tokens(tokens);
532 }
533 Ty::Never => {
534 tokens.append("!");
535 }
536 Ty::Tup(ref elems) => {
537 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700538 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700539 if elems.len() == 1 {
540 tokens.append(",");
541 }
542 tokens.append(")");
543 }
David Tolnayf69904a2016-09-04 14:46:07 -0700544 Ty::Path(None, ref path) => {
545 path.to_tokens(tokens);
546 }
547 Ty::Path(Some(ref qself), ref path) => {
548 tokens.append("<");
549 qself.ty.to_tokens(tokens);
550 if qself.position > 0 {
551 tokens.append("as");
David Tolnaydaaf7742016-10-03 11:11:43 -0700552 for (i, segment) in path.segments
553 .iter()
554 .take(qself.position)
555 .enumerate() {
David Tolnayf69904a2016-09-04 14:46:07 -0700556 if i > 0 || path.global {
557 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700558 }
David Tolnayf69904a2016-09-04 14:46:07 -0700559 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700560 }
David Tolnayf69904a2016-09-04 14:46:07 -0700561 }
562 tokens.append(">");
563 for segment in path.segments.iter().skip(qself.position) {
564 tokens.append("::");
565 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700566 }
567 }
David Tolnay6414da72016-10-08 00:55:17 -0700568 Ty::ObjectSum(ref ty, ref bounds) => {
569 ty.to_tokens(tokens);
570 for bound in bounds {
571 tokens.append("+");
572 bound.to_tokens(tokens);
573 }
574 }
575 Ty::PolyTraitRef(ref bounds) => {
576 tokens.append_separated(bounds, "+");
577 }
David Tolnay87d0b442016-09-04 11:52:12 -0700578 Ty::ImplTrait(ref bounds) => {
579 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700580 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700581 }
582 Ty::Paren(ref inner) => {
583 tokens.append("(");
584 inner.to_tokens(tokens);
585 tokens.append(")");
586 }
587 Ty::Infer => {
588 tokens.append("_");
589 }
590 }
591 }
592 }
593
David Tolnay47a877c2016-10-01 16:50:55 -0700594 impl ToTokens for Mutability {
595 fn to_tokens(&self, tokens: &mut Tokens) {
596 if let Mutability::Mutable = *self {
597 tokens.append("mut");
598 }
599 }
600 }
601
David Tolnay87d0b442016-09-04 11:52:12 -0700602 impl ToTokens for Path {
603 fn to_tokens(&self, tokens: &mut Tokens) {
604 for (i, segment) in self.segments.iter().enumerate() {
605 if i > 0 || self.global {
606 tokens.append("::");
607 }
608 segment.to_tokens(tokens);
609 }
610 }
611 }
612
613 impl ToTokens for PathSegment {
614 fn to_tokens(&self, tokens: &mut Tokens) {
615 self.ident.to_tokens(tokens);
616 self.parameters.to_tokens(tokens);
617 }
618 }
619
620 impl ToTokens for PathParameters {
621 fn to_tokens(&self, tokens: &mut Tokens) {
622 match *self {
623 PathParameters::AngleBracketed(ref parameters) => {
624 parameters.to_tokens(tokens);
625 }
626 PathParameters::Parenthesized(ref parameters) => {
627 parameters.to_tokens(tokens);
628 }
629 }
630 }
631 }
632
633 impl ToTokens for AngleBracketedParameterData {
634 fn to_tokens(&self, tokens: &mut Tokens) {
635 let has_lifetimes = !self.lifetimes.is_empty();
636 let has_types = !self.types.is_empty();
637 let has_bindings = !self.bindings.is_empty();
638 if !has_lifetimes && !has_types && !has_bindings {
639 return;
640 }
641
642 tokens.append("<");
643
644 let mut first = true;
645 for lifetime in &self.lifetimes {
646 if !first {
647 tokens.append(",");
648 }
649 lifetime.to_tokens(tokens);
650 first = false;
651 }
652 for ty in &self.types {
653 if !first {
654 tokens.append(",");
655 }
656 ty.to_tokens(tokens);
657 first = false;
658 }
659 for binding in &self.bindings {
660 if !first {
661 tokens.append(",");
662 }
663 binding.to_tokens(tokens);
664 first = false;
665 }
666
667 tokens.append(">");
668 }
669 }
670
671 impl ToTokens for TypeBinding {
672 fn to_tokens(&self, tokens: &mut Tokens) {
673 self.ident.to_tokens(tokens);
674 tokens.append("=");
675 self.ty.to_tokens(tokens);
676 }
677 }
678
679 impl ToTokens for ParenthesizedParameterData {
680 fn to_tokens(&self, tokens: &mut Tokens) {
681 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700682 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700683 tokens.append(")");
684 if let Some(ref output) = self.output {
685 tokens.append("->");
686 output.to_tokens(tokens);
687 }
688 }
689 }
690
691 impl ToTokens for PolyTraitRef {
692 fn to_tokens(&self, tokens: &mut Tokens) {
693 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700694 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700695 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700696 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700697 tokens.append(">");
698 }
699 self.trait_ref.to_tokens(tokens);
700 }
701 }
702
703 impl ToTokens for BareFnTy {
704 fn to_tokens(&self, tokens: &mut Tokens) {
705 tokens.append("fn");
706 if !self.lifetimes.is_empty() {
707 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700708 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700709 tokens.append(">");
710 }
711 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700712 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700713 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700714 if let FunctionRetTy::Ty(ref ty) = self.output {
715 tokens.append("->");
716 ty.to_tokens(tokens);
717 }
718 }
719 }
720
David Tolnay62f374c2016-10-02 13:37:00 -0700721 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700722 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700723 if let Some(ref name) = self.name {
724 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700725 tokens.append(":");
726 }
727 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700728 }
729 }
730}