blob: 1c4917bebde7b6f969bdcef009a6b1495cd233ab [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
David Tolnay84aa0752016-10-02 23:01:13 -070062impl<T> From<T> for Path where T: Into<PathSegment> {
63 fn from(segment: T) -> Self {
64 Path {
65 global: false,
66 segments: vec![segment.into()],
67 }
68 }
69}
70
David Tolnayb79ee962016-09-04 09:39:20 -070071/// A segment of a path: an identifier, an optional lifetime, and a set of types.
72///
73/// E.g. `std`, `String` or `Box<T>`
74#[derive(Debug, Clone, Eq, PartialEq)]
75pub struct PathSegment {
76 pub ident: Ident,
77 pub parameters: PathParameters,
78}
79
David Tolnay84aa0752016-10-02 23:01:13 -070080impl<T> From<T> for PathSegment where T: Into<Ident> {
81 fn from(ident: T) -> Self {
David Tolnayb79ee962016-09-04 09:39:20 -070082 PathSegment {
David Tolnay84aa0752016-10-02 23:01:13 -070083 ident: ident.into(),
David Tolnayb79ee962016-09-04 09:39:20 -070084 parameters: PathParameters::none(),
85 }
86 }
87}
88
89/// Parameters of a path segment.
90///
91/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
92#[derive(Debug, Clone, Eq, PartialEq)]
93pub enum PathParameters {
94 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
95 AngleBracketed(AngleBracketedParameterData),
96 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
97 Parenthesized(ParenthesizedParameterData),
98}
99
100impl PathParameters {
101 pub fn none() -> Self {
102 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
103 }
104}
105
106/// A path like `Foo<'a, T>`
107#[derive(Debug, Clone, Eq, PartialEq, Default)]
108pub struct AngleBracketedParameterData {
109 /// The lifetime parameters for this path segment.
110 pub lifetimes: Vec<Lifetime>,
111 /// The type parameters for this path segment, if present.
112 pub types: Vec<Ty>,
113 /// Bindings (equality constraints) on associated types, if present.
114 ///
115 /// E.g., `Foo<A=Bar>`.
116 pub bindings: Vec<TypeBinding>,
117}
118
119/// Bind a type to an associated type: `A=Foo`.
120#[derive(Debug, Clone, Eq, PartialEq)]
121pub struct TypeBinding {
122 pub ident: Ident,
123 pub ty: Ty,
124}
125
126/// A path like `Foo(A,B) -> C`
127#[derive(Debug, Clone, Eq, PartialEq)]
128pub struct ParenthesizedParameterData {
129 /// `(A, B)`
130 pub inputs: Vec<Ty>,
131 /// `C`
132 pub output: Option<Ty>,
133}
134
135#[derive(Debug, Clone, Eq, PartialEq)]
136pub struct PolyTraitRef {
137 /// The `'a` in `<'a> Foo<&'a T>`
138 pub bound_lifetimes: Vec<LifetimeDef>,
139 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
140 pub trait_ref: Path,
141}
142
143/// The explicit Self type in a "qualified path". The actual
144/// path, including the trait and the associated item, is stored
145/// separately. `position` represents the index of the associated
146/// item qualified with this Self type.
147///
148/// ```rust,ignore
149/// <Vec<T> as a::b::Trait>::AssociatedItem
150/// ^~~~~ ~~~~~~~~~~~~~~^
151/// ty position = 3
152///
153/// <Vec<T>>::AssociatedItem
154/// ^~~~~ ^
155/// ty position = 0
156/// ```
157#[derive(Debug, Clone, Eq, PartialEq)]
158pub struct QSelf {
159 pub ty: Box<Ty>,
160 pub position: usize
161}
162
163#[derive(Debug, Clone, Eq, PartialEq)]
164pub struct BareFnTy {
165 pub lifetimes: Vec<LifetimeDef>,
David Tolnay62f374c2016-10-02 13:37:00 -0700166 pub inputs: Vec<BareFnArg>,
David Tolnayb79ee962016-09-04 09:39:20 -0700167 pub output: FunctionRetTy,
168}
169
David Tolnay62f374c2016-10-02 13:37:00 -0700170/// An argument in a function type.
David Tolnayb79ee962016-09-04 09:39:20 -0700171///
172/// E.g. `bar: usize` as in `fn foo(bar: usize)`
173#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnay62f374c2016-10-02 13:37:00 -0700174pub struct BareFnArg {
175 pub name: Option<Ident>,
David Tolnayb79ee962016-09-04 09:39:20 -0700176 pub ty: Ty,
177}
178
179#[derive(Debug, Clone, Eq, PartialEq)]
180pub enum FunctionRetTy {
181 /// Return type is not specified.
182 ///
183 /// Functions default to `()` and
184 /// closures default to inference. Span points to where return
185 /// type would be inserted.
186 Default,
187 /// Everything else
188 Ty(Ty),
189}
190
David Tolnay86eca752016-09-04 11:26:41 -0700191#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700192pub mod parsing {
193 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700194 use generics::parsing::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay55337722016-09-11 12:58:56 -0700195 use ident::parsing::ident;
David Tolnayde206222016-09-30 11:47:01 -0700196 use lit::parsing::int;
David Tolnay9d8f1972016-09-04 11:58:48 -0700197 use std::str;
David Tolnayda4049b2016-09-04 10:59:23 -0700198
David Tolnayb5a7b142016-09-13 22:46:39 -0700199 named!(pub ty -> Ty, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700200 ty_vec
David Tolnayda4049b2016-09-04 10:59:23 -0700201 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700202 ty_fixed_length_vec
David Tolnayb79ee962016-09-04 09:39:20 -0700203 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700204 ty_ptr
205 |
206 ty_rptr
207 |
208 ty_bare_fn
209 |
210 ty_never
211 |
212 ty_tup
213 |
214 ty_path
215 |
David Tolnay9d8f1972016-09-04 11:58:48 -0700216 ty_impl_trait
217 |
218 ty_paren
219 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700220
David Tolnayb5a7b142016-09-13 22:46:39 -0700221 named!(ty_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700222 punct!("[") >>
223 elem: ty >>
224 punct!("]") >>
225 (Ty::Vec(Box::new(elem)))
226 ));
David Tolnayb79ee962016-09-04 09:39:20 -0700227
David Tolnayb5a7b142016-09-13 22:46:39 -0700228 named!(ty_fixed_length_vec -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700229 punct!("[") >>
230 elem: ty >>
231 punct!(";") >>
David Tolnayde206222016-09-30 11:47:01 -0700232 len: int >>
David Tolnayc94c38a2016-09-05 17:02:03 -0700233 punct!("]") >>
David Tolnayde206222016-09-30 11:47:01 -0700234 (Ty::FixedLengthVec(Box::new(elem), len.0 as usize))
David Tolnay9d8f1972016-09-04 11:58:48 -0700235 ));
236
David Tolnayb5a7b142016-09-13 22:46:39 -0700237 named!(ty_ptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700238 punct!("*") >>
David Tolnayb5a7b142016-09-13 22:46:39 -0700239 mutability: alt!(
David Tolnay10413f02016-09-30 09:12:02 -0700240 keyword!("const") => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700241 |
David Tolnay10413f02016-09-30 09:12:02 -0700242 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700243 ) >>
244 target: ty >>
245 (Ty::Ptr(Box::new(MutTy {
246 ty: target,
247 mutability: mutability,
248 })))
249 ));
250
David Tolnayb5a7b142016-09-13 22:46:39 -0700251 named!(ty_rptr -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700252 punct!("&") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700253 life: option!(lifetime) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700254 mutability: mutability >>
255 target: ty >>
256 (Ty::Rptr(life, Box::new(MutTy {
257 ty: target,
258 mutability: mutability,
259 })))
260 ));
261
David Tolnayb5a7b142016-09-13 22:46:39 -0700262 named!(ty_bare_fn -> Ty, do_parse!(
David Tolnay10413f02016-09-30 09:12:02 -0700263 keyword!("fn") >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700264 lifetimes: opt_vec!(delimited!(
265 punct!("<"),
266 separated_list!(punct!(","), lifetime_def),
267 punct!(">")
David Tolnay6b7aaf02016-09-04 10:39:25 -0700268 )) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700269 punct!("(") >>
270 inputs: separated_list!(punct!(","), fn_arg) >>
271 punct!(")") >>
David Tolnayf6ccb832016-09-04 15:00:56 -0700272 output: option!(preceded!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700273 punct!("->"),
274 ty
275 )) >>
276 (Ty::BareFn(Box::new(BareFnTy {
277 lifetimes: lifetimes,
David Tolnay62f374c2016-10-02 13:37:00 -0700278 inputs: inputs,
279 output: match output {
280 Some(ty) => FunctionRetTy::Ty(ty),
281 None => FunctionRetTy::Default,
David Tolnay9d8f1972016-09-04 11:58:48 -0700282 },
283 })))
284 ));
285
David Tolnayb5a7b142016-09-13 22:46:39 -0700286 named!(ty_never -> Ty, map!(punct!("!"), |_| Ty::Never));
David Tolnay9d8f1972016-09-04 11:58:48 -0700287
David Tolnayb5a7b142016-09-13 22:46:39 -0700288 named!(ty_tup -> Ty, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700289 punct!("(") >>
290 elems: separated_list!(punct!(","), ty) >>
291 punct!(")") >>
292 (Ty::Tup(elems))
293 ));
294
David Tolnay9636c052016-10-02 17:11:17 -0700295 named!(ty_path -> Ty, map!(qpath, |(qself, p)| Ty::Path(qself, p)));
David Tolnay9d8f1972016-09-04 11:58:48 -0700296
David Tolnay9636c052016-10-02 17:11:17 -0700297 named!(pub qpath -> (Option<QSelf>, Path), alt!(
298 map!(path, |p| (None, p))
299 |
300 do_parse!(
301 punct!("<") >>
302 this: map!(ty, Box::new) >>
303 path: option!(preceded!(
304 keyword!("as"),
305 path
306 )) >>
307 punct!(">") >>
308 punct!("::") >>
309 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
310 ({
311 match path {
312 Some(mut path) => {
313 let pos = path.segments.len();
314 path.segments.extend(rest);
315 (Some(QSelf { ty: this, position: pos }), path)
316 }
317 None => {
318 (Some(QSelf { ty: this, position: 0 }), Path {
319 global: false,
320 segments: rest,
321 })
322 }
David Tolnayb79ee962016-09-04 09:39:20 -0700323 }
David Tolnay9636c052016-10-02 17:11:17 -0700324 })
325 )
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 Tolnay47a877c2016-10-01 16:50:55 -0700341 named!(pub mutability -> Mutability, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700342 keyword!("mut") => { |_| Mutability::Mutable }
David Tolnayf6ccb832016-09-04 15:00:56 -0700343 |
344 epsilon!() => { |_| Mutability::Immutable }
David Tolnay9d8f1972016-09-04 11:58:48 -0700345 ));
346
David Tolnayb5a7b142016-09-13 22:46:39 -0700347 named!(pub path -> Path, do_parse!(
David Tolnayf6ccb832016-09-04 15:00:56 -0700348 global: option!(punct!("::")) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700349 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
350 (Path {
351 global: global.is_some(),
352 segments: segments,
353 })
354 ));
355
David Tolnay9636c052016-10-02 17:11:17 -0700356 named!(path_segment -> PathSegment, alt!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700357 do_parse!(
David Tolnay9636c052016-10-02 17:11:17 -0700358 id: option!(ident) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700359 punct!("<") >>
360 lifetimes: separated_list!(punct!(","), lifetime) >>
361 types: opt_vec!(preceded!(
362 cond!(!lifetimes.is_empty(), punct!(",")),
363 separated_nonempty_list!(
364 punct!(","),
365 terminated!(ty, not!(peek!(punct!("="))))
366 )
367 )) >>
368 bindings: opt_vec!(preceded!(
369 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
370 separated_nonempty_list!(punct!(","), type_binding)
371 )) >>
372 punct!(">") >>
373 (PathSegment {
David Tolnay9636c052016-10-02 17:11:17 -0700374 ident: id.unwrap_or_else(|| "".into()),
David Tolnay9d8f1972016-09-04 11:58:48 -0700375 parameters: PathParameters::AngleBracketed(
376 AngleBracketedParameterData {
377 lifetimes: lifetimes,
378 types: types,
379 bindings: bindings,
380 }
381 ),
382 })
383 )
384 |
David Tolnay84aa0752016-10-02 23:01:13 -0700385 map!(ident, Into::into)
David Tolnay9d8f1972016-09-04 11:58:48 -0700386 ));
387
David Tolnayb5a7b142016-09-13 22:46:39 -0700388 named!(type_binding -> TypeBinding, do_parse!(
David Tolnay55337722016-09-11 12:58:56 -0700389 id: ident >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700390 punct!("=") >>
391 ty: ty >>
392 (TypeBinding {
David Tolnay55337722016-09-11 12:58:56 -0700393 ident: id,
David Tolnay9d8f1972016-09-04 11:58:48 -0700394 ty: ty,
395 })
396 ));
397
David Tolnayb5a7b142016-09-13 22:46:39 -0700398 named!(pub poly_trait_ref -> PolyTraitRef, do_parse!(
David Tolnay9d8f1972016-09-04 11:58:48 -0700399 bound_lifetimes: bound_lifetimes >>
400 trait_ref: path >>
401 (PolyTraitRef {
402 bound_lifetimes: bound_lifetimes,
403 trait_ref: trait_ref,
404 })
405 ));
406
David Tolnay62f374c2016-10-02 13:37:00 -0700407 named!(pub fn_arg -> BareFnArg, do_parse!(
408 name: option!(terminated!(ident, punct!(":"))) >>
David Tolnay9d8f1972016-09-04 11:58:48 -0700409 ty: ty >>
David Tolnay62f374c2016-10-02 13:37:00 -0700410 (BareFnArg {
411 name: name,
David Tolnay9d8f1972016-09-04 11:58:48 -0700412 ty: ty,
413 })
414 ));
415}
David Tolnay87d0b442016-09-04 11:52:12 -0700416
417#[cfg(feature = "printing")]
418mod printing {
419 use super::*;
420 use quote::{Tokens, ToTokens};
421
422 impl ToTokens for Ty {
423 fn to_tokens(&self, tokens: &mut Tokens) {
424 match *self {
425 Ty::Vec(ref inner) => {
426 tokens.append("[");
427 inner.to_tokens(tokens);
428 tokens.append("]");
429 }
430 Ty::FixedLengthVec(ref inner, len) => {
431 tokens.append("[");
432 inner.to_tokens(tokens);
433 tokens.append(";");
David Tolnayde206222016-09-30 11:47:01 -0700434 tokens.append(&len.to_string());
David Tolnay87d0b442016-09-04 11:52:12 -0700435 tokens.append("]");
436 }
437 Ty::Ptr(ref target) => {
438 tokens.append("*");
439 match target.mutability {
440 Mutability::Mutable => tokens.append("mut"),
441 Mutability::Immutable => tokens.append("const"),
442 }
443 target.ty.to_tokens(tokens);
444 }
445 Ty::Rptr(ref lifetime, ref target) => {
446 tokens.append("&");
447 lifetime.to_tokens(tokens);
David Tolnay47a877c2016-10-01 16:50:55 -0700448 target.mutability.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700449 target.ty.to_tokens(tokens);
450 }
451 Ty::BareFn(ref func) => {
452 func.to_tokens(tokens);
453 }
454 Ty::Never => {
455 tokens.append("!");
456 }
457 Ty::Tup(ref elems) => {
458 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700459 tokens.append_separated(elems, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700460 if elems.len() == 1 {
461 tokens.append(",");
462 }
463 tokens.append(")");
464 }
David Tolnayf69904a2016-09-04 14:46:07 -0700465 Ty::Path(None, ref path) => {
466 path.to_tokens(tokens);
467 }
468 Ty::Path(Some(ref qself), ref path) => {
469 tokens.append("<");
470 qself.ty.to_tokens(tokens);
471 if qself.position > 0 {
472 tokens.append("as");
473 for (i, segment) in path.segments.iter()
474 .take(qself.position)
475 .enumerate()
476 {
477 if i > 0 || path.global {
478 tokens.append("::");
David Tolnay87d0b442016-09-04 11:52:12 -0700479 }
David Tolnayf69904a2016-09-04 14:46:07 -0700480 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700481 }
David Tolnayf69904a2016-09-04 14:46:07 -0700482 }
483 tokens.append(">");
484 for segment in path.segments.iter().skip(qself.position) {
485 tokens.append("::");
486 segment.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700487 }
488 }
489 Ty::ObjectSum(_, _) => unimplemented!(),
490 Ty::PolyTraitRef(_) => unimplemented!(),
491 Ty::ImplTrait(ref bounds) => {
492 tokens.append("impl");
David Tolnay94ebdf92016-09-04 13:33:16 -0700493 tokens.append_separated(bounds, "+");
David Tolnay87d0b442016-09-04 11:52:12 -0700494 }
495 Ty::Paren(ref inner) => {
496 tokens.append("(");
497 inner.to_tokens(tokens);
498 tokens.append(")");
499 }
500 Ty::Infer => {
501 tokens.append("_");
502 }
503 }
504 }
505 }
506
David Tolnay47a877c2016-10-01 16:50:55 -0700507 impl ToTokens for Mutability {
508 fn to_tokens(&self, tokens: &mut Tokens) {
509 if let Mutability::Mutable = *self {
510 tokens.append("mut");
511 }
512 }
513 }
514
David Tolnay87d0b442016-09-04 11:52:12 -0700515 impl ToTokens for Path {
516 fn to_tokens(&self, tokens: &mut Tokens) {
517 for (i, segment) in self.segments.iter().enumerate() {
518 if i > 0 || self.global {
519 tokens.append("::");
520 }
521 segment.to_tokens(tokens);
522 }
523 }
524 }
525
526 impl ToTokens for PathSegment {
527 fn to_tokens(&self, tokens: &mut Tokens) {
528 self.ident.to_tokens(tokens);
529 self.parameters.to_tokens(tokens);
530 }
531 }
532
533 impl ToTokens for PathParameters {
534 fn to_tokens(&self, tokens: &mut Tokens) {
535 match *self {
536 PathParameters::AngleBracketed(ref parameters) => {
537 parameters.to_tokens(tokens);
538 }
539 PathParameters::Parenthesized(ref parameters) => {
540 parameters.to_tokens(tokens);
541 }
542 }
543 }
544 }
545
546 impl ToTokens for AngleBracketedParameterData {
547 fn to_tokens(&self, tokens: &mut Tokens) {
548 let has_lifetimes = !self.lifetimes.is_empty();
549 let has_types = !self.types.is_empty();
550 let has_bindings = !self.bindings.is_empty();
551 if !has_lifetimes && !has_types && !has_bindings {
552 return;
553 }
554
555 tokens.append("<");
556
557 let mut first = true;
558 for lifetime in &self.lifetimes {
559 if !first {
560 tokens.append(",");
561 }
562 lifetime.to_tokens(tokens);
563 first = false;
564 }
565 for ty in &self.types {
566 if !first {
567 tokens.append(",");
568 }
569 ty.to_tokens(tokens);
570 first = false;
571 }
572 for binding in &self.bindings {
573 if !first {
574 tokens.append(",");
575 }
576 binding.to_tokens(tokens);
577 first = false;
578 }
579
580 tokens.append(">");
581 }
582 }
583
584 impl ToTokens for TypeBinding {
585 fn to_tokens(&self, tokens: &mut Tokens) {
586 self.ident.to_tokens(tokens);
587 tokens.append("=");
588 self.ty.to_tokens(tokens);
589 }
590 }
591
592 impl ToTokens for ParenthesizedParameterData {
593 fn to_tokens(&self, tokens: &mut Tokens) {
594 tokens.append("(");
David Tolnay94ebdf92016-09-04 13:33:16 -0700595 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700596 tokens.append(")");
597 if let Some(ref output) = self.output {
598 tokens.append("->");
599 output.to_tokens(tokens);
600 }
601 }
602 }
603
604 impl ToTokens for PolyTraitRef {
605 fn to_tokens(&self, tokens: &mut Tokens) {
606 if !self.bound_lifetimes.is_empty() {
David Tolnaye8796aa2016-09-04 14:48:22 -0700607 tokens.append("for");
David Tolnay87d0b442016-09-04 11:52:12 -0700608 tokens.append("<");
David Tolnay94ebdf92016-09-04 13:33:16 -0700609 tokens.append_separated(&self.bound_lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700610 tokens.append(">");
611 }
612 self.trait_ref.to_tokens(tokens);
613 }
614 }
615
616 impl ToTokens for BareFnTy {
617 fn to_tokens(&self, tokens: &mut Tokens) {
618 tokens.append("fn");
619 if !self.lifetimes.is_empty() {
620 tokens.append("<");
David Tolnay42602292016-10-01 22:25:45 -0700621 tokens.append_separated(&self.lifetimes, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700622 tokens.append(">");
623 }
624 tokens.append("(");
David Tolnay42602292016-10-01 22:25:45 -0700625 tokens.append_separated(&self.inputs, ",");
David Tolnay87d0b442016-09-04 11:52:12 -0700626 tokens.append(")");
David Tolnay42602292016-10-01 22:25:45 -0700627 if let FunctionRetTy::Ty(ref ty) = self.output {
628 tokens.append("->");
629 ty.to_tokens(tokens);
630 }
631 }
632 }
633
David Tolnay62f374c2016-10-02 13:37:00 -0700634 impl ToTokens for BareFnArg {
David Tolnay42602292016-10-01 22:25:45 -0700635 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay62f374c2016-10-02 13:37:00 -0700636 if let Some(ref name) = self.name {
637 name.to_tokens(tokens);
David Tolnay42602292016-10-01 22:25:45 -0700638 tokens.append(":");
639 }
640 self.ty.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700641 }
642 }
643}