blob: ec26c0dbcfd437f2ca0d990912d86db680cd2767 [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]`)
7 Vec(Box<Ty>),
8 /// A fixed length array (`[T; n]`)
9 FixedLengthVec(Box<Ty>, usize),
10 /// 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
62/// A segment of a path: an identifier, an optional lifetime, and a set of types.
63///
64/// E.g. `std`, `String` or `Box<T>`
65#[derive(Debug, Clone, Eq, PartialEq)]
66pub struct PathSegment {
67 pub ident: Ident,
68 pub parameters: PathParameters,
69}
70
71impl PathSegment {
72 pub fn ident(ident: Ident) -> Self {
73 PathSegment {
74 ident: ident,
75 parameters: PathParameters::none(),
76 }
77 }
78}
79
80/// Parameters of a path segment.
81///
82/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
83#[derive(Debug, Clone, Eq, PartialEq)]
84pub enum PathParameters {
85 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
86 AngleBracketed(AngleBracketedParameterData),
87 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
88 Parenthesized(ParenthesizedParameterData),
89}
90
91impl PathParameters {
92 pub fn none() -> Self {
93 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
94 }
95}
96
97/// A path like `Foo<'a, T>`
98#[derive(Debug, Clone, Eq, PartialEq, Default)]
99pub struct AngleBracketedParameterData {
100 /// The lifetime parameters for this path segment.
101 pub lifetimes: Vec<Lifetime>,
102 /// The type parameters for this path segment, if present.
103 pub types: Vec<Ty>,
104 /// Bindings (equality constraints) on associated types, if present.
105 ///
106 /// E.g., `Foo<A=Bar>`.
107 pub bindings: Vec<TypeBinding>,
108}
109
110/// Bind a type to an associated type: `A=Foo`.
111#[derive(Debug, Clone, Eq, PartialEq)]
112pub struct TypeBinding {
113 pub ident: Ident,
114 pub ty: Ty,
115}
116
117/// A path like `Foo(A,B) -> C`
118#[derive(Debug, Clone, Eq, PartialEq)]
119pub struct ParenthesizedParameterData {
120 /// `(A, B)`
121 pub inputs: Vec<Ty>,
122 /// `C`
123 pub output: Option<Ty>,
124}
125
126#[derive(Debug, Clone, Eq, PartialEq)]
127pub struct PolyTraitRef {
128 /// The `'a` in `<'a> Foo<&'a T>`
129 pub bound_lifetimes: Vec<LifetimeDef>,
130 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
131 pub trait_ref: Path,
132}
133
134/// The explicit Self type in a "qualified path". The actual
135/// path, including the trait and the associated item, is stored
136/// separately. `position` represents the index of the associated
137/// item qualified with this Self type.
138///
139/// ```rust,ignore
140/// <Vec<T> as a::b::Trait>::AssociatedItem
141/// ^~~~~ ~~~~~~~~~~~~~~^
142/// ty position = 3
143///
144/// <Vec<T>>::AssociatedItem
145/// ^~~~~ ^
146/// ty position = 0
147/// ```
148#[derive(Debug, Clone, Eq, PartialEq)]
149pub struct QSelf {
150 pub ty: Box<Ty>,
151 pub position: usize
152}
153
154#[derive(Debug, Clone, Eq, PartialEq)]
155pub struct BareFnTy {
156 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700157 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700158 pub output: FunctionRetTy,
159}
160
David Tolnay62f374c2016-10-02 13:37:00 -0700161/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700162///
163/// E.g. `bar: usize` as in `fn foo(bar: usize)`
164#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay62f374c2016-10-02 13:37:00 -0700165pub struct BareFnArg {
166 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700167 pub ty: Ty,
168}
169
170#[derive(Debug, Clone, Eq, PartialEq)]
171pub enum FunctionRetTy {
172 /// Return type is not specified.
173 ///
174 /// Functions default to `()` and
175 /// closures default to inference. Span points to where return
176 /// type would be inserted.
177 Default,
178 /// Everything else
179 Ty(Ty),
180}
181
David Tolnay86eca752016-09-04 11:26:41 -0700182#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700183pub mod parsing {
184 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700185 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700186 use ident::parsing::ident;
David Tolnayde206222016-09-30 11:47:01 -0700187 use lit::parsing::int;
David Tolnay9d8f1972016-09-04 11:58:48 -0700188 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700189
David Tolnayb5a7b142016-09-13 22:46:39 -0700190 named!(pub ty -> Ty, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700191 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700192 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700193 ty_fixed_length_vec
David Tolnayb79ee962016-09-04 09:39:20 -0700194 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700195 ty_ptr
196 |
197 ty_rptr
198 |
199 ty_bare_fn
200 |
201 ty_never
202 |
203 ty_tup
204 |
205 ty_path
206 |
207 ty_qpath
208 |
209 ty_impl_trait
210 |
211 ty_paren
212 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700213
David Tolnayb5a7b142016-09-13 22:46:39 -0700214 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700215 punct!("[") >>
216 elem: ty >>
217 punct!("]") >>
218 (Ty::Vec(Box::new(elem)))
219 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700220
David Tolnayb5a7b142016-09-13 22:46:39 -0700221 named!(ty_fixed_length_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700222 punct!("[") >>
223 elem: ty >>
224 punct!(";") >>
David Tolnayde206222016-09-30 11:47:01 -0700225 len: int >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700226 punct!("]") >>
David Tolnayde206222016-09-30 11:47:01 -0700227 (Ty::FixedLengthVec(Box::new(elem), len.0 as usize))
David Tolnay9d8f1972016-09-04 11:58:48 -0700228 ));
229
David Tolnayb5a7b142016-09-13 22:46:39 -0700230 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700231 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700232 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700233 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700234 |
David Tolnay10413f02016-09-30 09:12:02 -0700235 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700236 ) >>
237 target: ty >>
238 (Ty::Ptr(Box::new(MutTy {
239 ty: target,
240 mutability: mutability,
241 })))
242 ));
243
David Tolnayb5a7b142016-09-13 22:46:39 -0700244 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700245 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700246 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700247 mutability: mutability >>
248 target: ty >>
249 (Ty::Rptr(life, Box::new(MutTy {
250 ty: target,
251 mutability: mutability,
252 })))
253 ));
254
David Tolnayb5a7b142016-09-13 22:46:39 -0700255 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700256 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700257 lifetimes: opt_vec!(delimited!(
258 punct!("<"),
259 separated_list!(punct!(","), lifetime_def),
260 punct!(">")
David Tolnay6b7aaf02016-09-04 10:39:25 -0700261 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700262 punct!("(") >>
263 inputs: separated_list!(punct!(","), fn_arg) >>
264 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700265 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700266 punct!("->"),
267 ty
268 )) >>
269 (Ty::BareFn(Box::new(BareFnTy {
270 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700271 inputs: inputs,
272 output: match output {
273 Some(ty) => FunctionRetTy::Ty(ty),
274 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700275 },
276 })))
277 ));
278
David Tolnayb5a7b142016-09-13 22:46:39 -0700279 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700280
David Tolnayb5a7b142016-09-13 22:46:39 -0700281 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700282 punct!("(") >>
283 elems: separated_list!(punct!(","), ty) >>
284 punct!(")") >>
285 (Ty::Tup(elems))
286 ));
287
David Tolnayb5a7b142016-09-13 22:46:39 -0700288 named!(ty_path -> Ty, map!(path, |p| Ty::Path(None, p)));
David Tolnay9d8f1972016-09-04 11:58:48 -0700289
David Tolnayb5a7b142016-09-13 22:46:39 -0700290 named!(ty_qpath -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700291 punct!("<") >>
292 this: map!(ty, Box::new) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700293 path: option!(preceded!(
David Tolnay10413f02016-09-30 09:12:02 -0700294 keyword!("as"),
David Tolnay9d8f1972016-09-04 11:58:48 -0700295 path
David Tolnay6b7aaf02016-09-04 10:39:25 -0700296 )) >>
297 punct!(">") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700298 punct!("::") >>
299 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
300 ({
301 match path {
302 Some(mut path) => {
303 let pos = path.segments.len();
304 path.segments.extend(rest);
305 Ty::Path(Some(QSelf { ty: this, position: pos }), path)
David Tolnayb79ee962016-09-04 09:39:20 -0700306 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700307 None => {
308 Ty::Path(Some(QSelf { ty: this, position: 0 }), Path {
309 global: false,
310 segments: rest,
311 })
312 }
313 }
David Tolnay6b7aaf02016-09-04 10:39:25 -0700314 })
David Tolnay9d8f1972016-09-04 11:58:48 -0700315 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700316
David Tolnayb5a7b142016-09-13 22:46:39 -0700317 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700318 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700319 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
320 (Ty::ImplTrait(elem))
321 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700322
David Tolnayb5a7b142016-09-13 22:46:39 -0700323 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700324 punct!("(") >>
325 elem: ty >>
326 punct!(")") >>
327 (Ty::Paren(Box::new(elem)))
328 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700329
David Tolnay47a877c2016-10-01 16:50:55 -0700330 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700331 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700332 |
333 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700334 ));
335
David Tolnayb5a7b142016-09-13 22:46:39 -0700336 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700337 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700338 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
339 (Path {
340 global: global.is_some(),
341 segments: segments,
342 })
343 ));
344
David Tolnay89e05672016-10-02 14:39:42 -0700345 named!(pub path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700346 do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700347 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700348 punct!("<") >>
349 lifetimes: separated_list!(punct!(","), lifetime) >>
350 types: opt_vec!(preceded!(
351 cond!(!lifetimes.is_empty(), punct!(",")),
352 separated_nonempty_list!(
353 punct!(","),
354 terminated!(ty, not!(peek!(punct!("="))))
355 )
356 )) >>
357 bindings: opt_vec!(preceded!(
358 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
359 separated_nonempty_list!(punct!(","), type_binding)
360 )) >>
361 punct!(">") >>
362 (PathSegment {
David Tolnay55337722016-09-11 12:58:56 -0700363 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700364 parameters: PathParameters::AngleBracketed(
365 AngleBracketedParameterData {
366 lifetimes: lifetimes,
367 types: types,
368 bindings: bindings,
369 }
370 ),
371 })
372 )
373 |
David Tolnay55337722016-09-11 12:58:56 -0700374 map!(ident, PathSegment::ident)
David Tolnay9d8f1972016-09-04 11:58:48 -0700375 ));
376
David Tolnayb5a7b142016-09-13 22:46:39 -0700377 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700378 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700379 punct!("=") >>
380 ty: ty >>
381 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700382 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700383 ty: ty,
384 })
385 ));
386
David Tolnayb5a7b142016-09-13 22:46:39 -0700387 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700388 bound_lifetimes: bound_lifetimes >>
389 trait_ref: path >>
390 (PolyTraitRef {
391 bound_lifetimes: bound_lifetimes,
392 trait_ref: trait_ref,
393 })
394 ));
395
David Tolnay62f374c2016-10-02 13:37:00 -0700396 named!(pub fn_arg -> BareFnArg, do_parse!(
397 name: option!(terminated!(ident, punct!(":"))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700398 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700399 (BareFnArg {
400 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700401 ty: ty,
402 })
403 ));
404}
David Tolnay87d0b442016-09-04 11:52:12 -0700405
406#[cfg(feature = "printing")]
407mod printing {
408 use super::*;
409 use quote::{Tokens, ToTokens};
410
411 impl ToTokens for Ty {
412 fn to_tokens(&self, tokens: &mut Tokens) {
413 match *self {
414 Ty::Vec(ref inner) => {
415 tokens.append("[");
416 inner.to_tokens(tokens);
417 tokens.append("]");
418 }
419 Ty::FixedLengthVec(ref inner, len) => {
420 tokens.append("[");
421 inner.to_tokens(tokens);
422 tokens.append(";");
David Tolnayde206222016-09-30 11:47:01 -0700423 tokens.append(&len.to_string());
David Tolnay87d0b442016-09-04 11:52:12 -0700424 tokens.append("]");
425 }
426 Ty::Ptr(ref target) => {
427 tokens.append("*");
428 match target.mutability {
429 Mutability::Mutable => tokens.append("mut"),
430 Mutability::Immutable => tokens.append("const"),
431 }
432 target.ty.to_tokens(tokens);
433 }
434 Ty::Rptr(ref lifetime, ref target) => {
435 tokens.append("&");
436 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700437 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700438 target.ty.to_tokens(tokens);
439 }
440 Ty::BareFn(ref func) => {
441 func.to_tokens(tokens);
442 }
443 Ty::Never => {
444 tokens.append("!");
445 }
446 Ty::Tup(ref elems) => {
447 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700448 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700449 if elems.len() == 1 {
450 tokens.append(",");
451 }
452 tokens.append(")");
453 }
David Tolnayf69904a2016-09-04 14:46:07 -0700454 Ty::Path(None, ref path) => {
455 path.to_tokens(tokens);
456 }
457 Ty::Path(Some(ref qself), ref path) => {
458 tokens.append("<");
459 qself.ty.to_tokens(tokens);
460 if qself.position > 0 {
461 tokens.append("as");
462 for (i, segment) in path.segments.iter()
463 .take(qself.position)
464 .enumerate()
465 {
466 if i > 0 || path.global {
467 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700468 }
David Tolnayf69904a2016-09-04 14:46:07 -0700469 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700470 }
David Tolnayf69904a2016-09-04 14:46:07 -0700471 }
472 tokens.append(">");
473 for segment in path.segments.iter().skip(qself.position) {
474 tokens.append("::");
475 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700476 }
477 }
478 Ty::ObjectSum(_, _) => unimplemented!(),
479 Ty::PolyTraitRef(_) => unimplemented!(),
480 Ty::ImplTrait(ref bounds) => {
481 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700482 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700483 }
484 Ty::Paren(ref inner) => {
485 tokens.append("(");
486 inner.to_tokens(tokens);
487 tokens.append(")");
488 }
489 Ty::Infer => {
490 tokens.append("_");
491 }
492 }
493 }
494 }
495
David Tolnay47a877c2016-10-01 16:50:55 -0700496 impl ToTokens for Mutability {
497 fn to_tokens(&self, tokens: &mut Tokens) {
498 if let Mutability::Mutable = *self {
499 tokens.append("mut");
500 }
501 }
502 }
503
David Tolnay87d0b442016-09-04 11:52:12 -0700504 impl ToTokens for Path {
505 fn to_tokens(&self, tokens: &mut Tokens) {
506 for (i, segment) in self.segments.iter().enumerate() {
507 if i > 0 || self.global {
508 tokens.append("::");
509 }
510 segment.to_tokens(tokens);
511 }
512 }
513 }
514
515 impl ToTokens for PathSegment {
516 fn to_tokens(&self, tokens: &mut Tokens) {
517 self.ident.to_tokens(tokens);
518 self.parameters.to_tokens(tokens);
519 }
520 }
521
522 impl ToTokens for PathParameters {
523 fn to_tokens(&self, tokens: &mut Tokens) {
524 match *self {
525 PathParameters::AngleBracketed(ref parameters) => {
526 parameters.to_tokens(tokens);
527 }
528 PathParameters::Parenthesized(ref parameters) => {
529 parameters.to_tokens(tokens);
530 }
531 }
532 }
533 }
534
535 impl ToTokens for AngleBracketedParameterData {
536 fn to_tokens(&self, tokens: &mut Tokens) {
537 let has_lifetimes = !self.lifetimes.is_empty();
538 let has_types = !self.types.is_empty();
539 let has_bindings = !self.bindings.is_empty();
540 if !has_lifetimes && !has_types && !has_bindings {
541 return;
542 }
543
544 tokens.append("<");
545
546 let mut first = true;
547 for lifetime in &self.lifetimes {
548 if !first {
549 tokens.append(",");
550 }
551 lifetime.to_tokens(tokens);
552 first = false;
553 }
554 for ty in &self.types {
555 if !first {
556 tokens.append(",");
557 }
558 ty.to_tokens(tokens);
559 first = false;
560 }
561 for binding in &self.bindings {
562 if !first {
563 tokens.append(",");
564 }
565 binding.to_tokens(tokens);
566 first = false;
567 }
568
569 tokens.append(">");
570 }
571 }
572
573 impl ToTokens for TypeBinding {
574 fn to_tokens(&self, tokens: &mut Tokens) {
575 self.ident.to_tokens(tokens);
576 tokens.append("=");
577 self.ty.to_tokens(tokens);
578 }
579 }
580
581 impl ToTokens for ParenthesizedParameterData {
582 fn to_tokens(&self, tokens: &mut Tokens) {
583 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700584 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700585 tokens.append(")");
586 if let Some(ref output) = self.output {
587 tokens.append("->");
588 output.to_tokens(tokens);
589 }
590 }
591 }
592
593 impl ToTokens for PolyTraitRef {
594 fn to_tokens(&self, tokens: &mut Tokens) {
595 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700596 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700597 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700598 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700599 tokens.append(">");
600 }
601 self.trait_ref.to_tokens(tokens);
602 }
603 }
604
605 impl ToTokens for BareFnTy {
606 fn to_tokens(&self, tokens: &mut Tokens) {
607 tokens.append("fn");
608 if !self.lifetimes.is_empty() {
609 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700610 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700611 tokens.append(">");
612 }
613 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700614 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700615 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700616 if let FunctionRetTy::Ty(ref ty) = self.output {
617 tokens.append("->");
618 ty.to_tokens(tokens);
619 }
620 }
621 }
622
David Tolnay62f374c2016-10-02 13:37:00 -0700623 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700624 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700625 if let Some(ref name) = self.name {
626 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700627 tokens.append(":");
628 }
629 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700630 }
631 }
632}