blob: cdfa69773c32d762a90d8946fe15709e5d1240db [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
David Tolnayb79ee962016-09-04 09:39:20 -07003#[derive(Debug, Clone, Eq, PartialEq)]
4pub enum Ty {
5 /// A variable-length array (`[T]`)
6 Vec(Box<Ty>),
7 /// A fixed length array (`[T; n]`)
8 FixedLengthVec(Box<Ty>, usize),
9 /// A raw pointer (`*const T` or `*mut T`)
10 Ptr(Box<MutTy>),
11 /// A reference (`&'a T` or `&'a mut T`)
12 Rptr(Option<Lifetime>, Box<MutTy>),
13 /// A bare function (e.g. `fn(usize) -> bool`)
14 BareFn(Box<BareFnTy>),
15 /// The never type (`!`)
16 Never,
17 /// A tuple (`(A, B, C, D, ...)`)
18 Tup(Vec<Ty>),
19 /// A path (`module::module::...::Type`), optionally
20 /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
21 ///
22 /// Type parameters are stored in the Path itself
23 Path(Option<QSelf>, Path),
24 /// Something like `A+B`. Note that `B` must always be a path.
25 ObjectSum(Box<Ty>, Vec<TyParamBound>),
26 /// A type like `for<'a> Foo<&'a Bar>`
27 PolyTraitRef(Vec<TyParamBound>),
28 /// An `impl TraitA+TraitB` type.
29 ImplTrait(Vec<TyParamBound>),
30 /// No-op; kept solely so that we can pretty-print faithfully
31 Paren(Box<Ty>),
32 /// TyKind::Infer means the type should be inferred instead of it having been
33 /// specified. This can appear anywhere in a type.
34 Infer,
35}
36
37#[derive(Debug, Clone, Eq, PartialEq)]
38pub struct MutTy {
39 pub ty: Ty,
40 pub mutability: Mutability,
41}
42
David Tolnayf4bbbd92016-09-23 14:41:55 -070043#[derive(Debug, Copy, Clone, Eq, PartialEq)]
David Tolnayb79ee962016-09-04 09:39:20 -070044pub enum Mutability {
45 Mutable,
46 Immutable,
47}
48
49#[derive(Debug, Clone, Eq, PartialEq)]
50pub struct Path {
51 pub global: bool,
52 pub segments: Vec<PathSegment>,
53}
54
55/// A segment of a path: an identifier, an optional lifetime, and a set of types.
56///
57/// E.g. `std`, `String` or `Box<T>`
58#[derive(Debug, Clone, Eq, PartialEq)]
59pub struct PathSegment {
60 pub ident: Ident,
61 pub parameters: PathParameters,
62}
63
64impl PathSegment {
65 pub fn ident(ident: Ident) -> Self {
66 PathSegment {
67 ident: ident,
68 parameters: PathParameters::none(),
69 }
70 }
71}
72
73/// Parameters of a path segment.
74///
75/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
76#[derive(Debug, Clone, Eq, PartialEq)]
77pub enum PathParameters {
78 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
79 AngleBracketed(AngleBracketedParameterData),
80 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
81 Parenthesized(ParenthesizedParameterData),
82}
83
84impl PathParameters {
85 pub fn none() -> Self {
86 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
87 }
88}
89
90/// A path like `Foo<'a, T>`
91#[derive(Debug, Clone, Eq, PartialEq, Default)]
92pub struct AngleBracketedParameterData {
93 /// The lifetime parameters for this path segment.
94 pub lifetimes: Vec<Lifetime>,
95 /// The type parameters for this path segment, if present.
96 pub types: Vec<Ty>,
97 /// Bindings (equality constraints) on associated types, if present.
98 ///
99 /// E.g., `Foo<A=Bar>`.
100 pub bindings: Vec<TypeBinding>,
101}
102
103/// Bind a type to an associated type: `A=Foo`.
104#[derive(Debug, Clone, Eq, PartialEq)]
105pub struct TypeBinding {
106 pub ident: Ident,
107 pub ty: Ty,
108}
109
110/// A path like `Foo(A,B) -> C`
111#[derive(Debug, Clone, Eq, PartialEq)]
112pub struct ParenthesizedParameterData {
113 /// `(A, B)`
114 pub inputs: Vec<Ty>,
115 /// `C`
116 pub output: Option<Ty>,
117}
118
119#[derive(Debug, Clone, Eq, PartialEq)]
120pub struct PolyTraitRef {
121 /// The `'a` in `<'a> Foo<&'a T>`
122 pub bound_lifetimes: Vec<LifetimeDef>,
123 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
124 pub trait_ref: Path,
125}
126
127/// The explicit Self type in a "qualified path". The actual
128/// path, including the trait and the associated item, is stored
129/// separately. `position` represents the index of the associated
130/// item qualified with this Self type.
131///
132/// ```rust,ignore
133/// <Vec<T> as a::b::Trait>::AssociatedItem
134/// ^~~~~ ~~~~~~~~~~~~~~^
135/// ty position = 3
136///
137/// <Vec<T>>::AssociatedItem
138/// ^~~~~ ^
139/// ty position = 0
140/// ```
141#[derive(Debug, Clone, Eq, PartialEq)]
142pub struct QSelf {
143 pub ty: Box<Ty>,
144 pub position: usize
145}
146
147#[derive(Debug, Clone, Eq, PartialEq)]
148pub struct BareFnTy {
149 pub lifetimes: Vec<LifetimeDef>,
150 pub decl: FnDecl
151}
152
153/// Header (not the body) of a function declaration.
154///
155/// E.g. `fn foo(bar: baz)`
156#[derive(Debug, Clone, Eq, PartialEq)]
157pub struct FnDecl {
David Tolnay66daf742016-09-07 08:21:49 -0700158 pub inputs: Vec<FnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700159 pub output: FunctionRetTy,
160}
161
162/// An argument in a function header.
163///
164/// E.g. `bar: usize` as in `fn foo(bar: usize)`
165#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay66daf742016-09-07 08:21:49 -0700166pub struct FnArg {
David Tolnayb79ee962016-09-04 09:39:20 -0700167 pub pat: Option<Ident>,
168 pub ty: Ty,
169}
170
171#[derive(Debug, Clone, Eq, PartialEq)]
172pub enum FunctionRetTy {
173 /// Return type is not specified.
174 ///
175 /// Functions default to `()` and
176 /// closures default to inference. Span points to where return
177 /// type would be inserted.
178 Default,
179 /// Everything else
180 Ty(Ty),
181}
182
David Tolnay86eca752016-09-04 11:26:41 -0700183#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700184pub mod parsing {
185 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700186 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700187 use ident::parsing::ident;
David Tolnay9d8f1972016-09-04 11:58:48 -0700188 use nom::{digit, multispace};
189 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700190
David Tolnayb5a7b142016-09-13 22:46:39 -0700191 named!(pub ty -> Ty, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700192 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700193 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700194 ty_fixed_length_vec
David Tolnayb79ee962016-09-04 09:39:20 -0700195 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700196 ty_ptr
197 |
198 ty_rptr
199 |
200 ty_bare_fn
201 |
202 ty_never
203 |
204 ty_tup
205 |
206 ty_path
207 |
208 ty_qpath
209 |
210 ty_impl_trait
211 |
212 ty_paren
213 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700214
David Tolnayb5a7b142016-09-13 22:46:39 -0700215 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700216 punct!("[") >>
217 elem: ty >>
218 punct!("]") >>
219 (Ty::Vec(Box::new(elem)))
220 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700221
David Tolnayb5a7b142016-09-13 22:46:39 -0700222 named!(ty_fixed_length_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700223 punct!("[") >>
224 elem: ty >>
225 punct!(";") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700226 option!(multispace) >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700227 len: map_res!(digit, str::parse) >>
228 punct!("]") >>
229 (Ty::FixedLengthVec(Box::new(elem), len))
David Tolnay9d8f1972016-09-04 11:58:48 -0700230 ));
231
David Tolnayb5a7b142016-09-13 22:46:39 -0700232 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700233 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700234 mutability: alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700235 punct!("const") => { |_| Mutability::Immutable }
236 |
237 punct!("mut") => { |_| Mutability::Mutable }
238 ) >>
239 target: ty >>
240 (Ty::Ptr(Box::new(MutTy {
241 ty: target,
242 mutability: mutability,
243 })))
244 ));
245
David Tolnayb5a7b142016-09-13 22:46:39 -0700246 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700247 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700248 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700249 mutability: mutability >>
250 target: ty >>
251 (Ty::Rptr(life, Box::new(MutTy {
252 ty: target,
253 mutability: mutability,
254 })))
255 ));
256
David Tolnayb5a7b142016-09-13 22:46:39 -0700257 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700258 punct!("fn") >>
259 multispace >>
260 lifetimes: opt_vec!(delimited!(
261 punct!("<"),
262 separated_list!(punct!(","), lifetime_def),
263 punct!(">")
David Tolnay6b7aaf02016-09-04 10:39:25 -0700264 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700265 punct!("(") >>
266 inputs: separated_list!(punct!(","), fn_arg) >>
267 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700268 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700269 punct!("->"),
270 ty
271 )) >>
272 (Ty::BareFn(Box::new(BareFnTy {
273 lifetimes: lifetimes,
274 decl: FnDecl {
275 inputs: inputs,
276 output: match output {
277 Some(ty) => FunctionRetTy::Ty(ty),
278 None => FunctionRetTy::Default,
279 },
280 },
281 })))
282 ));
283
David Tolnayb5a7b142016-09-13 22:46:39 -0700284 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700285
David Tolnayb5a7b142016-09-13 22:46:39 -0700286 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700287 punct!("(") >>
288 elems: separated_list!(punct!(","), ty) >>
289 punct!(")") >>
290 (Ty::Tup(elems))
291 ));
292
David Tolnayb5a7b142016-09-13 22:46:39 -0700293 named!(ty_path -> Ty, map!(path, |p| Ty::Path(None, p)));
David Tolnay9d8f1972016-09-04 11:58:48 -0700294
David Tolnayb5a7b142016-09-13 22:46:39 -0700295 named!(ty_qpath -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700296 punct!("<") >>
297 this: map!(ty, Box::new) >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700298 path: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700299 tuple!(punct!("as"), multispace),
300 path
David Tolnay6b7aaf02016-09-04 10:39:25 -0700301 )) >>
302 punct!(">") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700303 punct!("::") >>
304 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
305 ({
306 match path {
307 Some(mut path) => {
308 let pos = path.segments.len();
309 path.segments.extend(rest);
310 Ty::Path(Some(QSelf { ty: this, position: pos }), path)
David Tolnayb79ee962016-09-04 09:39:20 -0700311 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700312 None => {
313 Ty::Path(Some(QSelf { ty: this, position: 0 }), Path {
314 global: false,
315 segments: rest,
316 })
317 }
318 }
David Tolnay6b7aaf02016-09-04 10:39:25 -0700319 })
David Tolnay9d8f1972016-09-04 11:58:48 -0700320 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700321
David Tolnayb5a7b142016-09-13 22:46:39 -0700322 named!(ty_impl_trait -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700323 punct!("impl") >>
324 multispace >>
325 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
326 (Ty::ImplTrait(elem))
327 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700328
David Tolnayb5a7b142016-09-13 22:46:39 -0700329 named!(ty_paren -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700330 punct!("(") >>
331 elem: ty >>
332 punct!(")") >>
333 (Ty::Paren(Box::new(elem)))
334 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700335
David Tolnayb5a7b142016-09-13 22:46:39 -0700336 named!(mutability -> Mutability, alt!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700337 do_parse!(
338 punct!("mut") >>
339 multispace >>
340 (Mutability::Mutable)
David Tolnay9d8f1972016-09-04 11:58:48 -0700341 )
David Tolnayf6ccb832016-09-04 15:00:56 -0700342 |
343 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700344 ));
345
David Tolnayb5a7b142016-09-13 22:46:39 -0700346 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700347 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700348 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
349 (Path {
350 global: global.is_some(),
351 segments: segments,
352 })
353 ));
354
David Tolnayb5a7b142016-09-13 22:46:39 -0700355 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700356 do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700357 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700358 punct!("<") >>
359 lifetimes: separated_list!(punct!(","), lifetime) >>
360 types: opt_vec!(preceded!(
361 cond!(!lifetimes.is_empty(), punct!(",")),
362 separated_nonempty_list!(
363 punct!(","),
364 terminated!(ty, not!(peek!(punct!("="))))
365 )
366 )) >>
367 bindings: opt_vec!(preceded!(
368 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
369 separated_nonempty_list!(punct!(","), type_binding)
370 )) >>
371 punct!(">") >>
372 (PathSegment {
David Tolnay55337722016-09-11 12:58:56 -0700373 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700374 parameters: PathParameters::AngleBracketed(
375 AngleBracketedParameterData {
376 lifetimes: lifetimes,
377 types: types,
378 bindings: bindings,
379 }
380 ),
381 })
382 )
383 |
David Tolnay55337722016-09-11 12:58:56 -0700384 map!(ident, PathSegment::ident)
David Tolnay9d8f1972016-09-04 11:58:48 -0700385 ));
386
David Tolnayb5a7b142016-09-13 22:46:39 -0700387 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700388 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700389 punct!("=") >>
390 ty: ty >>
391 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700392 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700393 ty: ty,
394 })
395 ));
396
David Tolnayb5a7b142016-09-13 22:46:39 -0700397 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700398 bound_lifetimes: bound_lifetimes >>
399 trait_ref: path >>
400 (PolyTraitRef {
401 bound_lifetimes: bound_lifetimes,
402 trait_ref: trait_ref,
403 })
404 ));
405
David Tolnayb5a7b142016-09-13 22:46:39 -0700406 named!(fn_arg -> FnArg, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700407 pat: option!(terminated!(ident, punct!(":"))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700408 ty: ty >>
David Tolnay66daf742016-09-07 08:21:49 -0700409 (FnArg {
David Tolnay9d8f1972016-09-04 11:58:48 -0700410 pat: pat,
411 ty: ty,
412 })
413 ));
414}
David Tolnay87d0b442016-09-04 11:52:12 -0700415
416#[cfg(feature = "printing")]
417mod printing {
418 use super::*;
419 use quote::{Tokens, ToTokens};
420
421 impl ToTokens for Ty {
422 fn to_tokens(&self, tokens: &mut Tokens) {
423 match *self {
424 Ty::Vec(ref inner) => {
425 tokens.append("[");
426 inner.to_tokens(tokens);
427 tokens.append("]");
428 }
429 Ty::FixedLengthVec(ref inner, len) => {
430 tokens.append("[");
431 inner.to_tokens(tokens);
432 tokens.append(";");
433 len.to_tokens(tokens);
434 tokens.append("]");
435 }
436 Ty::Ptr(ref target) => {
437 tokens.append("*");
438 match target.mutability {
439 Mutability::Mutable => tokens.append("mut"),
440 Mutability::Immutable => tokens.append("const"),
441 }
442 target.ty.to_tokens(tokens);
443 }
444 Ty::Rptr(ref lifetime, ref target) => {
445 tokens.append("&");
446 lifetime.to_tokens(tokens);
447 if let Mutability::Mutable = target.mutability {
448 tokens.append("mut");
449 }
450 target.ty.to_tokens(tokens);
451 }
452 Ty::BareFn(ref func) => {
453 func.to_tokens(tokens);
454 }
455 Ty::Never => {
456 tokens.append("!");
457 }
458 Ty::Tup(ref elems) => {
459 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700460 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700461 if elems.len() == 1 {
462 tokens.append(",");
463 }
464 tokens.append(")");
465 }
David Tolnayf69904a2016-09-04 14:46:07 -0700466 Ty::Path(None, ref path) => {
467 path.to_tokens(tokens);
468 }
469 Ty::Path(Some(ref qself), ref path) => {
470 tokens.append("<");
471 qself.ty.to_tokens(tokens);
472 if qself.position > 0 {
473 tokens.append("as");
474 for (i, segment) in path.segments.iter()
475 .take(qself.position)
476 .enumerate()
477 {
478 if i > 0 || path.global {
479 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700480 }
David Tolnayf69904a2016-09-04 14:46:07 -0700481 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700482 }
David Tolnayf69904a2016-09-04 14:46:07 -0700483 }
484 tokens.append(">");
485 for segment in path.segments.iter().skip(qself.position) {
486 tokens.append("::");
487 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700488 }
489 }
490 Ty::ObjectSum(_, _) => unimplemented!(),
491 Ty::PolyTraitRef(_) => unimplemented!(),
492 Ty::ImplTrait(ref bounds) => {
493 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700494 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700495 }
496 Ty::Paren(ref inner) => {
497 tokens.append("(");
498 inner.to_tokens(tokens);
499 tokens.append(")");
500 }
501 Ty::Infer => {
502 tokens.append("_");
503 }
504 }
505 }
506 }
507
508 impl ToTokens for Path {
509 fn to_tokens(&self, tokens: &mut Tokens) {
510 for (i, segment) in self.segments.iter().enumerate() {
511 if i > 0 || self.global {
512 tokens.append("::");
513 }
514 segment.to_tokens(tokens);
515 }
516 }
517 }
518
519 impl ToTokens for PathSegment {
520 fn to_tokens(&self, tokens: &mut Tokens) {
521 self.ident.to_tokens(tokens);
522 self.parameters.to_tokens(tokens);
523 }
524 }
525
526 impl ToTokens for PathParameters {
527 fn to_tokens(&self, tokens: &mut Tokens) {
528 match *self {
529 PathParameters::AngleBracketed(ref parameters) => {
530 parameters.to_tokens(tokens);
531 }
532 PathParameters::Parenthesized(ref parameters) => {
533 parameters.to_tokens(tokens);
534 }
535 }
536 }
537 }
538
539 impl ToTokens for AngleBracketedParameterData {
540 fn to_tokens(&self, tokens: &mut Tokens) {
541 let has_lifetimes = !self.lifetimes.is_empty();
542 let has_types = !self.types.is_empty();
543 let has_bindings = !self.bindings.is_empty();
544 if !has_lifetimes && !has_types && !has_bindings {
545 return;
546 }
547
548 tokens.append("<");
549
550 let mut first = true;
551 for lifetime in &self.lifetimes {
552 if !first {
553 tokens.append(",");
554 }
555 lifetime.to_tokens(tokens);
556 first = false;
557 }
558 for ty in &self.types {
559 if !first {
560 tokens.append(",");
561 }
562 ty.to_tokens(tokens);
563 first = false;
564 }
565 for binding in &self.bindings {
566 if !first {
567 tokens.append(",");
568 }
569 binding.to_tokens(tokens);
570 first = false;
571 }
572
573 tokens.append(">");
574 }
575 }
576
577 impl ToTokens for TypeBinding {
578 fn to_tokens(&self, tokens: &mut Tokens) {
579 self.ident.to_tokens(tokens);
580 tokens.append("=");
581 self.ty.to_tokens(tokens);
582 }
583 }
584
585 impl ToTokens for ParenthesizedParameterData {
586 fn to_tokens(&self, tokens: &mut Tokens) {
587 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700588 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700589 tokens.append(")");
590 if let Some(ref output) = self.output {
591 tokens.append("->");
592 output.to_tokens(tokens);
593 }
594 }
595 }
596
597 impl ToTokens for PolyTraitRef {
598 fn to_tokens(&self, tokens: &mut Tokens) {
599 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700600 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700601 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700602 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700603 tokens.append(">");
604 }
605 self.trait_ref.to_tokens(tokens);
606 }
607 }
608
609 impl ToTokens for BareFnTy {
610 fn to_tokens(&self, tokens: &mut Tokens) {
611 tokens.append("fn");
612 if !self.lifetimes.is_empty() {
613 tokens.append("<");
614 for (i, lifetime) in self.lifetimes.iter().enumerate() {
615 if i > 0 {
616 tokens.append(",");
617 }
618 lifetime.to_tokens(tokens);
619 }
620 tokens.append(">");
621 }
622 tokens.append("(");
623 tokens.append(")");
624 }
625 }
626}