blob: 6bae061fa06704545adafd8a18e6091869c53b15 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayb79ee962016-09-04 09:39:20 -07009use super::*;
David Tolnayf2cfd722017-12-31 18:02:51 -050010use punctuated::Punctuated;
David Tolnayb79ee962016-09-04 09:39:20 -070011
Alex Crichton62a0a592017-05-22 13:58:53 -070012ast_struct! {
13 /// Represents lifetimes and type parameters attached to a declaration
14 /// of a function, enum, trait, etc.
15 #[derive(Default)]
16 pub struct Generics {
David Tolnayf8db7ba2017-11-11 22:52:16 -080017 pub lt_token: Option<Token![<]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050018 pub params: Punctuated<GenericParam, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080019 pub gt_token: Option<Token![>]>,
David Tolnayac997dd2017-12-27 23:18:22 -050020 pub where_clause: Option<WhereClause>,
Alex Crichton62a0a592017-05-22 13:58:53 -070021 }
David Tolnayb79ee962016-09-04 09:39:20 -070022}
23
David Tolnayc2f1aba2017-11-12 20:29:22 -080024ast_enum_of_structs! {
25 pub enum GenericParam {
David Tolnayc2f1aba2017-11-12 20:29:22 -080026 /// A generic type parameter, e.g. `T: Into<String>`.
27 pub Type(TypeParam {
28 pub attrs: Vec<Attribute>,
29 pub ident: Ident,
30 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050031 pub bounds: Punctuated<TypeParamBound, Token![+]>,
David Tolnayc2f1aba2017-11-12 20:29:22 -080032 pub eq_token: Option<Token![=]>,
33 pub default: Option<Type>,
34 }),
David Tolnay517f3692018-01-01 20:17:23 -080035 /// A lifetime definition, e.g. `'a: 'b+'c+'d`
36 pub Lifetime(LifetimeDef {
37 pub attrs: Vec<Attribute>,
38 pub lifetime: Lifetime,
39 pub colon_token: Option<Token![:]>,
40 pub bounds: Punctuated<Lifetime, Token![+]>,
41 }),
Nika Layzellf1fdc0b2017-12-04 19:58:32 -050042 /// A generic const parameter, e.g. `const LENGTH: usize`.
43 pub Const(ConstParam {
44 pub attrs: Vec<Attribute>,
45 pub const_token: Token![const],
46 pub ident: Ident,
47 pub colon_token: Token![:],
48 pub ty: Type,
49 pub eq_token: Option<Token![=]>,
50 pub default: Option<Expr>,
51 }),
David Tolnayc2f1aba2017-11-12 20:29:22 -080052 }
53}
54
David Tolnaye7678922016-10-13 20:44:03 -070055#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040056#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
57#[cfg_attr(feature = "clone-impls", derive(Clone))]
58/// Returned by `Generics::split_for_impl`.
59pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -070060
61#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040062#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
63#[cfg_attr(feature = "clone-impls", derive(Clone))]
64/// Returned by `Generics::split_for_impl`.
David Tolnayfd6bf5c2017-11-12 09:41:14 -080065pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -070066
David Tolnayc879a502017-01-25 15:51:32 -080067#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040068#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
69#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -080070/// Returned by `TypeGenerics::as_turbofish`.
Nika Layzell6b38b132017-10-24 23:09:39 -040071pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -080072
David Tolnaye95cc9f2017-01-25 15:57:09 -080073#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -070074impl Generics {
75 /// Split a type's generics into the pieces required for impl'ing a trait
76 /// for that type.
77 ///
78 /// ```
79 /// # extern crate syn;
80 /// # #[macro_use]
81 /// # extern crate quote;
82 /// # fn main() {
83 /// # let generics: syn::Generics = Default::default();
Alex Crichtonccbb45d2017-05-23 10:58:24 -070084 /// # let name = syn::Ident::from("MyType");
David Tolnayb153dbc2016-10-04 23:39:10 -070085 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
86 /// quote! {
87 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
88 /// // ...
89 /// }
90 /// }
91 /// # ;
92 /// # }
93 /// ```
David Tolnayac997dd2017-12-27 23:18:22 -050094 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -080095 (
96 ImplGenerics(self),
97 TypeGenerics(self),
98 self.where_clause.as_ref(),
99 )
David Tolnayb153dbc2016-10-04 23:39:10 -0700100 }
101}
102
David Tolnaye95cc9f2017-01-25 15:57:09 -0800103#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800104impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -0800105 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
106 pub fn as_turbofish(&self) -> Turbofish {
107 Turbofish(self.0)
108 }
109}
110
Alex Crichton62a0a592017-05-22 13:58:53 -0700111ast_struct! {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700112 /// A set of bound lifetimes, e.g. `for<'a, 'b, 'c>`
113 #[derive(Default)]
114 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800115 pub for_token: Token![for],
116 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500117 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800118 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700119 }
120}
121
David Tolnayf9505b52016-10-02 09:18:52 -0700122impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700123 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700124 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700125 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700126 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700127 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500128 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700129 }
130 }
131}
132
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800133impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700134 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800135 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700136 attrs: vec![],
137 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700138 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500139 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700140 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700141 default: None,
142 }
143 }
144}
145
David Tolnay40fb8ce2018-01-02 10:53:46 -0800146ast_enum_of_structs! {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800147 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800148 pub Trait(TraitBound),
149 pub Lifetime(Lifetime),
150 }
151}
152
153ast_struct! {
154 pub struct TraitBound {
155 pub modifier: TraitBoundModifier,
156 /// The `for<'a>` in `for<'a> Foo<&'a T>`
157 pub lifetimes: Option<BoundLifetimes>,
158 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
159 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700160 }
David Tolnay55337722016-09-11 12:58:56 -0700161}
162
Alex Crichton62a0a592017-05-22 13:58:53 -0700163ast_enum! {
164 /// A modifier on a bound, currently this is only used for `?Sized`, where the
David Tolnay40fb8ce2018-01-02 10:53:46 -0800165 /// modifier is `Maybe`.
Alex Crichton2e0229c2017-05-23 09:34:50 -0700166 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700167 pub enum TraitBoundModifier {
168 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800169 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700170 }
David Tolnay55337722016-09-11 12:58:56 -0700171}
172
Alex Crichton62a0a592017-05-22 13:58:53 -0700173ast_struct! {
174 /// A `where` clause in a definition
Alex Crichton62a0a592017-05-22 13:58:53 -0700175 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500176 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500177 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700178 }
David Tolnayb79ee962016-09-04 09:39:20 -0700179}
180
Alex Crichton62a0a592017-05-22 13:58:53 -0700181ast_enum_of_structs! {
182 /// A single predicate in a `where` clause
183 pub enum WherePredicate {
184 /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
David Tolnayd4add852018-01-01 20:13:24 -0800185 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700186 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800187 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700188 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800189 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800190 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700191 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500192 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700193 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700194
Alex Crichton62a0a592017-05-22 13:58:53 -0700195 /// A lifetime predicate, e.g. `'a: 'b+'c`
David Tolnayd4add852018-01-01 20:13:24 -0800196 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700197 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800198 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500199 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700200 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700201
Alex Crichton62a0a592017-05-22 13:58:53 -0700202 /// An equality predicate (unsupported)
David Tolnayd4add852018-01-01 20:13:24 -0800203 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800204 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800205 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800206 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700207 }),
208 }
David Tolnayf8e08832017-01-23 00:04:32 -0800209}
210
David Tolnay86eca752016-09-04 11:26:41 -0700211#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700212pub mod parsing {
213 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700214
David Tolnay63e3dee2017-06-03 20:13:17 -0700215 use synom::Synom;
David Tolnayf2cfd722017-12-31 18:02:51 -0500216 use punctuated::Element;
Alex Crichton954046c2017-05-30 21:49:42 -0700217
218 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400219 named!(parse -> Self, map!(
220 alt!(
221 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800222 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500223 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400224 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800225 lifetimes.empty_or_trailing(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500226 Punctuated::<TypeParam, Token![,]>::parse_terminated
Michael Layzell92639a52017-06-01 00:07:44 -0400227 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800228 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400229 (lifetimes, ty_params, Some(lt), Some(gt))
230 )
231 |
David Tolnayf2cfd722017-12-31 18:02:51 -0500232 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
Michael Layzell92639a52017-06-01 00:07:44 -0400233 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700234 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400235 lt_token: lt,
David Tolnay6eff4da2018-01-01 20:27:45 -0800236 params: lifetimes.into_elements()
David Tolnayc2f1aba2017-11-12 20:29:22 -0800237 .map(Element::into_tuple)
David Tolnay660fd1f2017-12-31 01:52:57 -0500238 .map(|(life, comma)| Element::new(GenericParam::Lifetime(life), comma))
David Tolnayc2f1aba2017-11-12 20:29:22 -0800239 .chain(ty_params.unwrap_or_default()
David Tolnay6eff4da2018-01-01 20:27:45 -0800240 .into_elements()
David Tolnayc2f1aba2017-11-12 20:29:22 -0800241 .map(Element::into_tuple)
David Tolnay660fd1f2017-12-31 01:52:57 -0500242 .map(|(ty, comma)| Element::new(GenericParam::Type(ty), comma)))
243 .collect(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800244 gt_token: gt,
David Tolnayac997dd2017-12-27 23:18:22 -0500245 where_clause: None,
Michael Layzell416724e2017-05-24 21:12:34 -0400246 }
Michael Layzell92639a52017-06-01 00:07:44 -0400247 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800248
249 fn description() -> Option<&'static str> {
250 Some("generic parameters in declaration")
251 }
Alex Crichton954046c2017-05-30 21:49:42 -0700252 }
253
Alex Crichton954046c2017-05-30 21:49:42 -0700254 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400255 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500256 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400257 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800258 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400259 bounds: cond!(
260 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500261 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400262 ) >>
263 (LifetimeDef {
264 attrs: attrs,
265 lifetime: life,
266 bounds: bounds.unwrap_or_default(),
David Tolnay6af8f1d2017-12-27 23:08:43 -0500267 colon_token: colon,
Michael Layzell92639a52017-06-01 00:07:44 -0400268 })
269 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800270
271 fn description() -> Option<&'static str> {
272 Some("lifetime definition")
273 }
Alex Crichton954046c2017-05-30 21:49:42 -0700274 }
275
276 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400277 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800278 for_: keyword!(for) >>
279 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500280 lifetimes: call!(Punctuated::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800281 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400282 (BoundLifetimes {
283 for_token: for_,
284 lt_token: lt,
285 gt_token: gt,
286 lifetimes: lifetimes,
287 })
288 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800289
290 fn description() -> Option<&'static str> {
291 Some("bound lifetimes")
292 }
Alex Crichton954046c2017-05-30 21:49:42 -0700293 }
David Tolnay55337722016-09-11 12:58:56 -0700294
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800295 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400296 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500297 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400298 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800299 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400300 bounds: cond!(
301 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500302 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400303 ) >>
304 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800305 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800306 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400307 (eq, ty)
308 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800309 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400310 attrs: attrs,
311 ident: id,
312 bounds: bounds.unwrap_or_default(),
313 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800314 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400315 default: default.map(|d| d.1),
316 })
317 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800318
319 fn description() -> Option<&'static str> {
320 Some("type parameter")
321 }
Alex Crichton954046c2017-05-30 21:49:42 -0700322 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700323
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800324 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400325 named!(parse -> Self, alt!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800326 syn!(Lifetime) => { TypeParamBound::Lifetime }
Michael Layzell92639a52017-06-01 00:07:44 -0400327 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800328 syn!(TraitBound) => { TypeParamBound::Trait }
Michael Layzell92639a52017-06-01 00:07:44 -0400329 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800330 parens!(syn!(TraitBound)) => { |bound| TypeParamBound::Trait(bound.1) }
Michael Layzell92639a52017-06-01 00:07:44 -0400331 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700332
333 fn description() -> Option<&'static str> {
Nika Layzellc691cb42017-12-04 13:44:38 -0500334 Some("type parameter bound")
Alex Crichton954046c2017-05-30 21:49:42 -0700335 }
336 }
337
David Tolnay40fb8ce2018-01-02 10:53:46 -0800338 impl Synom for TraitBound {
339 named!(parse -> Self, do_parse!(
340 modifier: syn!(TraitBoundModifier) >>
341 lifetimes: option!(syn!(BoundLifetimes)) >>
342 mut path: syn!(Path) >>
343 parenthesized: option!(cond_reduce!(
344 path.segments.last().unwrap().item().arguments.is_empty(),
345 syn!(ParenthesizedGenericArguments)
346 )) >>
347 ({
348 if let Some(parenthesized) = parenthesized {
349 let parenthesized = PathArguments::Parenthesized(parenthesized);
350 path.segments.last_mut().unwrap().item_mut().arguments = parenthesized;
351 }
352 TraitBound {
353 modifier: modifier,
354 lifetimes: lifetimes,
355 path: path,
356 }
357 })
358 ));
359
360 fn description() -> Option<&'static str> {
361 Some("trait bound")
362 }
363 }
364
365 impl Synom for TraitBoundModifier {
366 named!(parse -> Self, alt!(
367 punct!(?) => { TraitBoundModifier::Maybe }
368 |
369 epsilon!() => { |_| TraitBoundModifier::None }
370 ));
371
372 fn description() -> Option<&'static str> {
373 Some("trait bound modifier")
374 }
375 }
376
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500377 impl Synom for ConstParam {
378 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500379 attrs: many0!(Attribute::parse_outer) >>
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500380 const_: keyword!(const) >>
381 ident: syn!(Ident) >>
382 colon: punct!(:) >>
383 ty: syn!(Type) >>
384 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
David Tolnay78ee5202017-12-04 22:17:54 -0800385 ({
386 let (eq_token, default) = match eq_def {
387 Some((eq_token, default)) => (Some(eq_token), Some(default)),
388 None => (None, None),
389 };
390 ConstParam {
391 attrs: attrs,
392 const_token: const_,
393 ident: ident,
394 colon_token: colon,
395 ty: ty,
396 eq_token: eq_token,
397 default: default,
398 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500399 })
400 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800401
402 fn description() -> Option<&'static str> {
403 Some("generic `const` parameter")
404 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500405 }
406
Alex Crichton954046c2017-05-30 21:49:42 -0700407 impl Synom for WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500408 named!(parse -> Self, do_parse!(
409 where_: keyword!(where) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500410 predicates: call!(Punctuated::parse_terminated) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500411 (WhereClause {
412 predicates: predicates,
413 where_token: where_,
414 })
Michael Layzell92639a52017-06-01 00:07:44 -0400415 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700416
417 fn description() -> Option<&'static str> {
418 Some("where clause")
419 }
420 }
421
422 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400423 named!(parse -> Self, alt!(
424 do_parse!(
425 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800426 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400427 bounds: cond!(
428 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500429 Punctuated::parse_separated
Michael Layzell92639a52017-06-01 00:07:44 -0400430 ) >>
David Tolnayd4add852018-01-01 20:13:24 -0800431 (WherePredicate::Lifetime(PredicateLifetime {
Michael Layzell92639a52017-06-01 00:07:44 -0400432 lifetime: ident,
433 bounds: bounds.unwrap_or_default(),
434 colon_token: colon,
435 }))
436 )
437 |
438 do_parse!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800439 lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800440 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800441 colon: punct!(:) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500442 bounds: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayd4add852018-01-01 20:13:24 -0800443 (WherePredicate::Type(PredicateType {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800444 lifetimes: lifetimes,
Michael Layzell92639a52017-06-01 00:07:44 -0400445 bounded_ty: bounded_ty,
446 bounds: bounds,
447 colon_token: colon,
448 }))
449 )
450 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800451
452 fn description() -> Option<&'static str> {
453 Some("predicate in where clause")
454 }
Alex Crichton954046c2017-05-30 21:49:42 -0700455 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700456}
David Tolnay87d0b442016-09-04 11:52:12 -0700457
458#[cfg(feature = "printing")]
459mod printing {
460 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700461 use attr::FilterAttrs;
David Tolnay51382052017-12-27 13:46:21 -0500462 use quote::{ToTokens, Tokens};
David Tolnay87d0b442016-09-04 11:52:12 -0700463
Michael Layzell3936ceb2017-07-08 00:28:36 -0400464 /// Returns true if the generics object has no lifetimes or ty_params.
465 fn empty_normal_generics(generics: &Generics) -> bool {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800466 generics.params.is_empty()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400467 }
468
David Tolnay8ef93042016-09-04 14:08:40 -0700469 impl ToTokens for Generics {
470 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400471 if empty_normal_generics(self) {
472 return;
473 }
474
Alex Crichton259ee532017-07-14 06:51:02 -0700475 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800476 self.params.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700477 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700478 }
479 }
480
David Tolnaye7678922016-10-13 20:44:03 -0700481 impl<'a> ToTokens for ImplGenerics<'a> {
482 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500483 if empty_normal_generics(self.0) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400484 return;
485 }
486
Alex Crichton259ee532017-07-14 06:51:02 -0700487 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay6eff4da2018-01-01 20:27:45 -0800488 for param in self.0.params.elements() {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800489 match **param.item() {
490 GenericParam::Lifetime(ref param) => {
491 param.to_tokens(tokens);
492 }
493 GenericParam::Type(ref param) => {
494 // Leave off the type parameter defaults
495 tokens.append_all(param.attrs.outer());
496 param.ident.to_tokens(tokens);
497 if !param.bounds.is_empty() {
498 TokensOrDefault(&param.colon_token).to_tokens(tokens);
499 param.bounds.to_tokens(tokens);
500 }
501 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500502 GenericParam::Const(ref param) => {
503 // Leave off the const parameter defaults
504 tokens.append_all(param.attrs.outer());
505 param.const_token.to_tokens(tokens);
506 param.ident.to_tokens(tokens);
507 param.colon_token.to_tokens(tokens);
508 param.ty.to_tokens(tokens);
509 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400510 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500511 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700512 }
Alex Crichton259ee532017-07-14 06:51:02 -0700513 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700514 }
515 }
516
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800517 impl<'a> ToTokens for TypeGenerics<'a> {
David Tolnaye7678922016-10-13 20:44:03 -0700518 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500519 if empty_normal_generics(self.0) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400520 return;
521 }
522
Alex Crichton259ee532017-07-14 06:51:02 -0700523 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay6eff4da2018-01-01 20:27:45 -0800524 for param in self.0.params.elements() {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800525 match **param.item() {
526 GenericParam::Lifetime(ref param) => {
527 // Leave off the lifetime bounds and attributes
528 param.lifetime.to_tokens(tokens);
529 }
530 GenericParam::Type(ref param) => {
531 // Leave off the type parameter defaults
532 param.ident.to_tokens(tokens);
533 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500534 GenericParam::Const(ref param) => {
535 // Leave off the const parameter defaults
536 param.ident.to_tokens(tokens);
537 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800538 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500539 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700540 }
Alex Crichton259ee532017-07-14 06:51:02 -0700541 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700542 }
543 }
544
David Tolnayc879a502017-01-25 15:51:32 -0800545 impl<'a> ToTokens for Turbofish<'a> {
546 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500547 if !empty_normal_generics(self.0) {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800548 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800549 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800550 }
551 }
552 }
553
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700554 impl ToTokens for BoundLifetimes {
555 fn to_tokens(&self, tokens: &mut Tokens) {
556 self.for_token.to_tokens(tokens);
557 self.lt_token.to_tokens(tokens);
558 self.lifetimes.to_tokens(tokens);
559 self.gt_token.to_tokens(tokens);
560 }
561 }
562
David Tolnay87d0b442016-09-04 11:52:12 -0700563 impl ToTokens for LifetimeDef {
564 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700565 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700566 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400567 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700568 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400569 self.bounds.to_tokens(tokens);
570 }
David Tolnay87d0b442016-09-04 11:52:12 -0700571 }
572 }
573
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800574 impl ToTokens for TypeParam {
David Tolnay8ef93042016-09-04 14:08:40 -0700575 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700576 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700577 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400578 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700579 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400580 self.bounds.to_tokens(tokens);
581 }
582 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700583 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400584 self.default.to_tokens(tokens);
585 }
David Tolnay8ef93042016-09-04 14:08:40 -0700586 }
587 }
588
David Tolnay40fb8ce2018-01-02 10:53:46 -0800589 impl ToTokens for TraitBound {
David Tolnay87d0b442016-09-04 11:52:12 -0700590 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800591 self.modifier.to_tokens(tokens);
592 self.lifetimes.to_tokens(tokens);
593 self.path.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700594 }
595 }
596
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700597 impl ToTokens for TraitBoundModifier {
598 fn to_tokens(&self, tokens: &mut Tokens) {
599 match *self {
600 TraitBoundModifier::None => {}
601 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
602 }
603 }
604 }
605
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500606 impl ToTokens for ConstParam {
607 fn to_tokens(&self, tokens: &mut Tokens) {
608 tokens.append_all(self.attrs.outer());
609 self.const_token.to_tokens(tokens);
610 self.ident.to_tokens(tokens);
611 self.colon_token.to_tokens(tokens);
612 self.ty.to_tokens(tokens);
613 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -0800614 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500615 self.default.to_tokens(tokens);
616 }
617 }
618 }
619
David Tolnay55337722016-09-11 12:58:56 -0700620 impl ToTokens for WhereClause {
621 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnayac997dd2017-12-27 23:18:22 -0500622 self.where_token.to_tokens(tokens);
623 self.predicates.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700624 }
625 }
David Tolnay8ef93042016-09-04 14:08:40 -0700626
David Tolnayd4add852018-01-01 20:13:24 -0800627 impl ToTokens for PredicateType {
David Tolnay8ef93042016-09-04 14:08:40 -0700628 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800629 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700630 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700631 self.colon_token.to_tokens(tokens);
632 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700633 }
634 }
635
David Tolnayd4add852018-01-01 20:13:24 -0800636 impl ToTokens for PredicateLifetime {
David Tolnay8ef93042016-09-04 14:08:40 -0700637 fn to_tokens(&self, tokens: &mut Tokens) {
638 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400639 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700640 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400641 self.bounds.to_tokens(tokens);
642 }
David Tolnay8ef93042016-09-04 14:08:40 -0700643 }
644 }
David Tolnayf8e08832017-01-23 00:04:32 -0800645
David Tolnayd4add852018-01-01 20:13:24 -0800646 impl ToTokens for PredicateEq {
David Tolnayf8e08832017-01-23 00:04:32 -0800647 fn to_tokens(&self, tokens: &mut Tokens) {
648 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700649 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -0800650 self.rhs_ty.to_tokens(tokens);
651 }
652 }
David Tolnay87d0b442016-09-04 11:52:12 -0700653}