blob: 35b640d78ee12c4dcb10371203ec8fbfac151d29 [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>,
157 pub decl: FnDecl
158}
159
160/// Header (not the body) of a function declaration.
161///
162/// E.g. `fn foo(bar: baz)`
163#[derive(Debug, Clone, Eq, PartialEq)]
164pub struct FnDecl {
David Tolnay66daf742016-09-07 08:21:49 -0700165 pub inputs: Vec<FnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700166 pub output: FunctionRetTy,
167}
168
169/// An argument in a function header.
170///
171/// E.g. `bar: usize` as in `fn foo(bar: usize)`
172#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay66daf742016-09-07 08:21:49 -0700173pub struct FnArg {
David Tolnayb79ee962016-09-04 09:39:20 -0700174 pub pat: Option<Ident>,
175 pub ty: Ty,
176}
177
178#[derive(Debug, Clone, Eq, PartialEq)]
179pub enum FunctionRetTy {
180 /// Return type is not specified.
181 ///
182 /// Functions default to `()` and
183 /// closures default to inference. Span points to where return
184 /// type would be inserted.
185 Default,
186 /// Everything else
187 Ty(Ty),
188}
189
David Tolnay86eca752016-09-04 11:26:41 -0700190#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700191pub mod parsing {
192 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700193 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700194 use ident::parsing::ident;
David Tolnay9d8f1972016-09-04 11:58:48 -0700195 use nom::{digit, multispace};
196 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700197
David Tolnayb5a7b142016-09-13 22:46:39 -0700198 named!(pub ty -> Ty, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700199 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700200 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700201 ty_fixed_length_vec
David Tolnayb79ee962016-09-04 09:39:20 -0700202 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700203 ty_ptr
204 |
205 ty_rptr
206 |
207 ty_bare_fn
208 |
209 ty_never
210 |
211 ty_tup
212 |
213 ty_path
214 |
215 ty_qpath
216 |
217 ty_impl_trait
218 |
219 ty_paren
220 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700221
David Tolnayb5a7b142016-09-13 22:46:39 -0700222 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700223 punct!("[") >>
224 elem: ty >>
225 punct!("]") >>
226 (Ty::Vec(Box::new(elem)))
227 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700228
David Tolnayb5a7b142016-09-13 22:46:39 -0700229 named!(ty_fixed_length_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700230 punct!("[") >>
231 elem: ty >>
232 punct!(";") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700233 option!(multispace) >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700234 len: map_res!(digit, str::parse) >>
235 punct!("]") >>
236 (Ty::FixedLengthVec(Box::new(elem), len))
David Tolnay9d8f1972016-09-04 11:58:48 -0700237 ));
238
David Tolnayb5a7b142016-09-13 22:46:39 -0700239 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700240 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700241 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700242 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700243 |
David Tolnay10413f02016-09-30 09:12:02 -0700244 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700245 ) >>
246 target: ty >>
247 (Ty::Ptr(Box::new(MutTy {
248 ty: target,
249 mutability: mutability,
250 })))
251 ));
252
David Tolnayb5a7b142016-09-13 22:46:39 -0700253 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700254 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700255 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700256 mutability: mutability >>
257 target: ty >>
258 (Ty::Rptr(life, Box::new(MutTy {
259 ty: target,
260 mutability: mutability,
261 })))
262 ));
263
David Tolnayb5a7b142016-09-13 22:46:39 -0700264 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700265 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700266 lifetimes: opt_vec!(delimited!(
267 punct!("<"),
268 separated_list!(punct!(","), lifetime_def),
269 punct!(">")
David Tolnay6b7aaf02016-09-04 10:39:25 -0700270 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700271 punct!("(") >>
272 inputs: separated_list!(punct!(","), fn_arg) >>
273 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700274 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700275 punct!("->"),
276 ty
277 )) >>
278 (Ty::BareFn(Box::new(BareFnTy {
279 lifetimes: lifetimes,
280 decl: FnDecl {
281 inputs: inputs,
282 output: match output {
283 Some(ty) => FunctionRetTy::Ty(ty),
284 None => FunctionRetTy::Default,
285 },
286 },
287 })))
288 ));
289
David Tolnayb5a7b142016-09-13 22:46:39 -0700290 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700291
David Tolnayb5a7b142016-09-13 22:46:39 -0700292 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700293 punct!("(") >>
294 elems: separated_list!(punct!(","), ty) >>
295 punct!(")") >>
296 (Ty::Tup(elems))
297 ));
298
David Tolnayb5a7b142016-09-13 22:46:39 -0700299 named!(ty_path -> Ty, map!(path, |p| Ty::Path(None, p)));
David Tolnay9d8f1972016-09-04 11:58:48 -0700300
David Tolnayb5a7b142016-09-13 22:46:39 -0700301 named!(ty_qpath -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700302 punct!("<") >>
303 this: map!(ty, Box::new) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700304 path: option!(preceded!(
David Tolnay10413f02016-09-30 09:12:02 -0700305 keyword!("as"),
David Tolnay9d8f1972016-09-04 11:58:48 -0700306 path
David Tolnay6b7aaf02016-09-04 10:39:25 -0700307 )) >>
308 punct!(">") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700309 punct!("::") >>
310 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
311 ({
312 match path {
313 Some(mut path) => {
314 let pos = path.segments.len();
315 path.segments.extend(rest);
316 Ty::Path(Some(QSelf { ty: this, position: pos }), path)
David Tolnayb79ee962016-09-04 09:39:20 -0700317 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700318 None => {
319 Ty::Path(Some(QSelf { ty: this, position: 0 }), Path {
320 global: false,
321 segments: rest,
322 })
323 }
324 }
David Tolnay6b7aaf02016-09-04 10:39:25 -0700325 })
David Tolnay9d8f1972016-09-04 11:58:48 -0700326 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700327
David Tolnayb5a7b142016-09-13 22:46:39 -0700328 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700329 keyword!("impl") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700330 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
331 (Ty::ImplTrait(elem))
332 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700333
David Tolnayb5a7b142016-09-13 22:46:39 -0700334 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700335 punct!("(") >>
336 elem: ty >>
337 punct!(")") >>
338 (Ty::Paren(Box::new(elem)))
339 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700340
David Tolnayb5a7b142016-09-13 22:46:39 -0700341 named!(mutability -> Mutability, alt!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700342 do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700343 keyword!("mut") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700344 (Mutability::Mutable)
David Tolnay9d8f1972016-09-04 11:58:48 -0700345 )
David Tolnayf6ccb832016-09-04 15:00:56 -0700346 |
347 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700348 ));
349
David Tolnayb5a7b142016-09-13 22:46:39 -0700350 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700351 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700352 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
353 (Path {
354 global: global.is_some(),
355 segments: segments,
356 })
357 ));
358
David Tolnayb5a7b142016-09-13 22:46:39 -0700359 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700360 do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700361 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700362 punct!("<") >>
363 lifetimes: separated_list!(punct!(","), lifetime) >>
364 types: opt_vec!(preceded!(
365 cond!(!lifetimes.is_empty(), punct!(",")),
366 separated_nonempty_list!(
367 punct!(","),
368 terminated!(ty, not!(peek!(punct!("="))))
369 )
370 )) >>
371 bindings: opt_vec!(preceded!(
372 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
373 separated_nonempty_list!(punct!(","), type_binding)
374 )) >>
375 punct!(">") >>
376 (PathSegment {
David Tolnay55337722016-09-11 12:58:56 -0700377 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700378 parameters: PathParameters::AngleBracketed(
379 AngleBracketedParameterData {
380 lifetimes: lifetimes,
381 types: types,
382 bindings: bindings,
383 }
384 ),
385 })
386 )
387 |
David Tolnay55337722016-09-11 12:58:56 -0700388 map!(ident, PathSegment::ident)
David Tolnay9d8f1972016-09-04 11:58:48 -0700389 ));
390
David Tolnayb5a7b142016-09-13 22:46:39 -0700391 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700392 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700393 punct!("=") >>
394 ty: ty >>
395 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700396 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700397 ty: ty,
398 })
399 ));
400
David Tolnayb5a7b142016-09-13 22:46:39 -0700401 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700402 bound_lifetimes: bound_lifetimes >>
403 trait_ref: path >>
404 (PolyTraitRef {
405 bound_lifetimes: bound_lifetimes,
406 trait_ref: trait_ref,
407 })
408 ));
409
David Tolnayb5a7b142016-09-13 22:46:39 -0700410 named!(fn_arg -> FnArg, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700411 pat: option!(terminated!(ident, punct!(":"))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700412 ty: ty >>
David Tolnay66daf742016-09-07 08:21:49 -0700413 (FnArg {
David Tolnay9d8f1972016-09-04 11:58:48 -0700414 pat: pat,
415 ty: ty,
416 })
417 ));
418}
David Tolnay87d0b442016-09-04 11:52:12 -0700419
420#[cfg(feature = "printing")]
421mod printing {
422 use super::*;
423 use quote::{Tokens, ToTokens};
424
425 impl ToTokens for Ty {
426 fn to_tokens(&self, tokens: &mut Tokens) {
427 match *self {
428 Ty::Vec(ref inner) => {
429 tokens.append("[");
430 inner.to_tokens(tokens);
431 tokens.append("]");
432 }
433 Ty::FixedLengthVec(ref inner, len) => {
434 tokens.append("[");
435 inner.to_tokens(tokens);
436 tokens.append(";");
437 len.to_tokens(tokens);
438 tokens.append("]");
439 }
440 Ty::Ptr(ref target) => {
441 tokens.append("*");
442 match target.mutability {
443 Mutability::Mutable => tokens.append("mut"),
444 Mutability::Immutable => tokens.append("const"),
445 }
446 target.ty.to_tokens(tokens);
447 }
448 Ty::Rptr(ref lifetime, ref target) => {
449 tokens.append("&");
450 lifetime.to_tokens(tokens);
451 if let Mutability::Mutable = target.mutability {
452 tokens.append("mut");
453 }
454 target.ty.to_tokens(tokens);
455 }
456 Ty::BareFn(ref func) => {
457 func.to_tokens(tokens);
458 }
459 Ty::Never => {
460 tokens.append("!");
461 }
462 Ty::Tup(ref elems) => {
463 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700464 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700465 if elems.len() == 1 {
466 tokens.append(",");
467 }
468 tokens.append(")");
469 }
David Tolnayf69904a2016-09-04 14:46:07 -0700470 Ty::Path(None, ref path) => {
471 path.to_tokens(tokens);
472 }
473 Ty::Path(Some(ref qself), ref path) => {
474 tokens.append("<");
475 qself.ty.to_tokens(tokens);
476 if qself.position > 0 {
477 tokens.append("as");
478 for (i, segment) in path.segments.iter()
479 .take(qself.position)
480 .enumerate()
481 {
482 if i > 0 || path.global {
483 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700484 }
David Tolnayf69904a2016-09-04 14:46:07 -0700485 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700486 }
David Tolnayf69904a2016-09-04 14:46:07 -0700487 }
488 tokens.append(">");
489 for segment in path.segments.iter().skip(qself.position) {
490 tokens.append("::");
491 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700492 }
493 }
494 Ty::ObjectSum(_, _) => unimplemented!(),
495 Ty::PolyTraitRef(_) => unimplemented!(),
496 Ty::ImplTrait(ref bounds) => {
497 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700498 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700499 }
500 Ty::Paren(ref inner) => {
501 tokens.append("(");
502 inner.to_tokens(tokens);
503 tokens.append(")");
504 }
505 Ty::Infer => {
506 tokens.append("_");
507 }
508 }
509 }
510 }
511
512 impl ToTokens for Path {
513 fn to_tokens(&self, tokens: &mut Tokens) {
514 for (i, segment) in self.segments.iter().enumerate() {
515 if i > 0 || self.global {
516 tokens.append("::");
517 }
518 segment.to_tokens(tokens);
519 }
520 }
521 }
522
523 impl ToTokens for PathSegment {
524 fn to_tokens(&self, tokens: &mut Tokens) {
525 self.ident.to_tokens(tokens);
526 self.parameters.to_tokens(tokens);
527 }
528 }
529
530 impl ToTokens for PathParameters {
531 fn to_tokens(&self, tokens: &mut Tokens) {
532 match *self {
533 PathParameters::AngleBracketed(ref parameters) => {
534 parameters.to_tokens(tokens);
535 }
536 PathParameters::Parenthesized(ref parameters) => {
537 parameters.to_tokens(tokens);
538 }
539 }
540 }
541 }
542
543 impl ToTokens for AngleBracketedParameterData {
544 fn to_tokens(&self, tokens: &mut Tokens) {
545 let has_lifetimes = !self.lifetimes.is_empty();
546 let has_types = !self.types.is_empty();
547 let has_bindings = !self.bindings.is_empty();
548 if !has_lifetimes && !has_types && !has_bindings {
549 return;
550 }
551
552 tokens.append("<");
553
554 let mut first = true;
555 for lifetime in &self.lifetimes {
556 if !first {
557 tokens.append(",");
558 }
559 lifetime.to_tokens(tokens);
560 first = false;
561 }
562 for ty in &self.types {
563 if !first {
564 tokens.append(",");
565 }
566 ty.to_tokens(tokens);
567 first = false;
568 }
569 for binding in &self.bindings {
570 if !first {
571 tokens.append(",");
572 }
573 binding.to_tokens(tokens);
574 first = false;
575 }
576
577 tokens.append(">");
578 }
579 }
580
581 impl ToTokens for TypeBinding {
582 fn to_tokens(&self, tokens: &mut Tokens) {
583 self.ident.to_tokens(tokens);
584 tokens.append("=");
585 self.ty.to_tokens(tokens);
586 }
587 }
588
589 impl ToTokens for ParenthesizedParameterData {
590 fn to_tokens(&self, tokens: &mut Tokens) {
591 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700592 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700593 tokens.append(")");
594 if let Some(ref output) = self.output {
595 tokens.append("->");
596 output.to_tokens(tokens);
597 }
598 }
599 }
600
601 impl ToTokens for PolyTraitRef {
602 fn to_tokens(&self, tokens: &mut Tokens) {
603 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700604 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700605 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700606 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700607 tokens.append(">");
608 }
609 self.trait_ref.to_tokens(tokens);
610 }
611 }
612
613 impl ToTokens for BareFnTy {
614 fn to_tokens(&self, tokens: &mut Tokens) {
615 tokens.append("fn");
616 if !self.lifetimes.is_empty() {
617 tokens.append("<");
618 for (i, lifetime) in self.lifetimes.iter().enumerate() {
619 if i > 0 {
620 tokens.append(",");
621 }
622 lifetime.to_tokens(tokens);
623 }
624 tokens.append(">");
625 }
626 tokens.append("(");
627 tokens.append(")");
628 }
629 }
630}