blob: 7206e3199eb2888a71f87e1b74418813fe6f6514 [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
David Tolnayf2cfd722017-12-31 18:02:51 -05002use punctuated::Punctuated;
David Tolnayb79ee962016-09-04 09:39:20 -07003
Alex Crichton62a0a592017-05-22 13:58:53 -07004ast_struct! {
5 /// Represents lifetimes and type parameters attached to a declaration
6 /// of a function, enum, trait, etc.
7 #[derive(Default)]
8 pub struct Generics {
David Tolnayf8db7ba2017-11-11 22:52:16 -08009 pub lt_token: Option<Token![<]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050010 pub params: Punctuated<GenericParam, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -080011 pub gt_token: Option<Token![>]>,
David Tolnayac997dd2017-12-27 23:18:22 -050012 pub where_clause: Option<WhereClause>,
Alex Crichton62a0a592017-05-22 13:58:53 -070013 }
David Tolnayb79ee962016-09-04 09:39:20 -070014}
15
David Tolnayc2f1aba2017-11-12 20:29:22 -080016ast_enum_of_structs! {
17 pub enum GenericParam {
David Tolnayc2f1aba2017-11-12 20:29:22 -080018 /// A generic type parameter, e.g. `T: Into<String>`.
19 pub Type(TypeParam {
20 pub attrs: Vec<Attribute>,
21 pub ident: Ident,
22 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050023 pub bounds: Punctuated<TypeParamBound, Token![+]>,
David Tolnayc2f1aba2017-11-12 20:29:22 -080024 pub eq_token: Option<Token![=]>,
25 pub default: Option<Type>,
26 }),
David Tolnay517f3692018-01-01 20:17:23 -080027 /// A lifetime definition, e.g. `'a: 'b+'c+'d`
28 pub Lifetime(LifetimeDef {
29 pub attrs: Vec<Attribute>,
30 pub lifetime: Lifetime,
31 pub colon_token: Option<Token![:]>,
32 pub bounds: Punctuated<Lifetime, Token![+]>,
33 }),
Nika Layzellf1fdc0b2017-12-04 19:58:32 -050034 /// A generic const parameter, e.g. `const LENGTH: usize`.
35 pub Const(ConstParam {
36 pub attrs: Vec<Attribute>,
37 pub const_token: Token![const],
38 pub ident: Ident,
39 pub colon_token: Token![:],
40 pub ty: Type,
41 pub eq_token: Option<Token![=]>,
42 pub default: Option<Expr>,
43 }),
David Tolnayc2f1aba2017-11-12 20:29:22 -080044 }
45}
46
David Tolnaye7678922016-10-13 20:44:03 -070047#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040048#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
49#[cfg_attr(feature = "clone-impls", derive(Clone))]
50/// Returned by `Generics::split_for_impl`.
51pub struct ImplGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -070052
53#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040054#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
55#[cfg_attr(feature = "clone-impls", derive(Clone))]
56/// Returned by `Generics::split_for_impl`.
David Tolnayfd6bf5c2017-11-12 09:41:14 -080057pub struct TypeGenerics<'a>(&'a Generics);
David Tolnaye7678922016-10-13 20:44:03 -070058
David Tolnayc879a502017-01-25 15:51:32 -080059#[cfg(feature = "printing")]
Nika Layzell6b38b132017-10-24 23:09:39 -040060#[cfg_attr(feature = "extra-traits", derive(Debug, Eq, PartialEq, Hash))]
61#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayfd6bf5c2017-11-12 09:41:14 -080062/// Returned by `TypeGenerics::as_turbofish`.
Nika Layzell6b38b132017-10-24 23:09:39 -040063pub struct Turbofish<'a>(&'a Generics);
David Tolnayc879a502017-01-25 15:51:32 -080064
David Tolnaye95cc9f2017-01-25 15:57:09 -080065#[cfg(feature = "printing")]
David Tolnayb153dbc2016-10-04 23:39:10 -070066impl Generics {
67 /// Split a type's generics into the pieces required for impl'ing a trait
68 /// for that type.
69 ///
70 /// ```
71 /// # extern crate syn;
72 /// # #[macro_use]
73 /// # extern crate quote;
74 /// # fn main() {
75 /// # let generics: syn::Generics = Default::default();
Alex Crichtonccbb45d2017-05-23 10:58:24 -070076 /// # let name = syn::Ident::from("MyType");
David Tolnayb153dbc2016-10-04 23:39:10 -070077 /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
78 /// quote! {
79 /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
80 /// // ...
81 /// }
82 /// }
83 /// # ;
84 /// # }
85 /// ```
David Tolnayac997dd2017-12-27 23:18:22 -050086 pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
David Tolnay61037c62018-01-05 16:21:03 -080087 (
88 ImplGenerics(self),
89 TypeGenerics(self),
90 self.where_clause.as_ref(),
91 )
David Tolnayb153dbc2016-10-04 23:39:10 -070092 }
93}
94
David Tolnaye95cc9f2017-01-25 15:57:09 -080095#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -080096impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -080097 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
98 pub fn as_turbofish(&self) -> Turbofish {
99 Turbofish(self.0)
100 }
101}
102
Alex Crichton62a0a592017-05-22 13:58:53 -0700103ast_struct! {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700104 /// A set of bound lifetimes, e.g. `for<'a, 'b, 'c>`
105 #[derive(Default)]
106 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800107 pub for_token: Token![for],
108 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500109 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800110 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700111 }
112}
113
David Tolnayf9505b52016-10-02 09:18:52 -0700114impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700115 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700116 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700117 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700118 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700119 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500120 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700121 }
122 }
123}
124
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800125impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700126 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800127 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700128 attrs: vec![],
129 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700130 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500131 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700132 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700133 default: None,
134 }
135 }
136}
137
David Tolnay40fb8ce2018-01-02 10:53:46 -0800138ast_enum_of_structs! {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800139 pub enum TypeParamBound {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800140 pub Trait(TraitBound),
141 pub Lifetime(Lifetime),
142 }
143}
144
145ast_struct! {
146 pub struct TraitBound {
147 pub modifier: TraitBoundModifier,
148 /// The `for<'a>` in `for<'a> Foo<&'a T>`
149 pub lifetimes: Option<BoundLifetimes>,
150 /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
151 pub path: Path,
Alex Crichton62a0a592017-05-22 13:58:53 -0700152 }
David Tolnay55337722016-09-11 12:58:56 -0700153}
154
Alex Crichton62a0a592017-05-22 13:58:53 -0700155ast_enum! {
156 /// A modifier on a bound, currently this is only used for `?Sized`, where the
David Tolnay40fb8ce2018-01-02 10:53:46 -0800157 /// modifier is `Maybe`.
Alex Crichton2e0229c2017-05-23 09:34:50 -0700158 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700159 pub enum TraitBoundModifier {
160 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800161 Maybe(Token![?]),
Alex Crichton62a0a592017-05-22 13:58:53 -0700162 }
David Tolnay55337722016-09-11 12:58:56 -0700163}
164
Alex Crichton62a0a592017-05-22 13:58:53 -0700165ast_struct! {
166 /// A `where` clause in a definition
Alex Crichton62a0a592017-05-22 13:58:53 -0700167 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500168 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500169 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700170 }
David Tolnayb79ee962016-09-04 09:39:20 -0700171}
172
Alex Crichton62a0a592017-05-22 13:58:53 -0700173ast_enum_of_structs! {
174 /// A single predicate in a `where` clause
175 pub enum WherePredicate {
176 /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
David Tolnayd4add852018-01-01 20:13:24 -0800177 pub Type(PredicateType {
Alex Crichton62a0a592017-05-22 13:58:53 -0700178 /// Any lifetimes from a `for` binding
David Tolnay40fb8ce2018-01-02 10:53:46 -0800179 pub lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700180 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800181 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800182 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700183 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500184 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700185 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700186
Alex Crichton62a0a592017-05-22 13:58:53 -0700187 /// A lifetime predicate, e.g. `'a: 'b+'c`
David Tolnayd4add852018-01-01 20:13:24 -0800188 pub Lifetime(PredicateLifetime {
Alex Crichton62a0a592017-05-22 13:58:53 -0700189 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800190 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500191 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700192 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700193
Alex Crichton62a0a592017-05-22 13:58:53 -0700194 /// An equality predicate (unsupported)
David Tolnayd4add852018-01-01 20:13:24 -0800195 pub Eq(PredicateEq {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800196 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800197 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800198 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700199 }),
200 }
David Tolnayf8e08832017-01-23 00:04:32 -0800201}
202
David Tolnay86eca752016-09-04 11:26:41 -0700203#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700204pub mod parsing {
205 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700206
David Tolnay63e3dee2017-06-03 20:13:17 -0700207 use synom::Synom;
David Tolnayf2cfd722017-12-31 18:02:51 -0500208 use punctuated::Element;
Alex Crichton954046c2017-05-30 21:49:42 -0700209
210 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400211 named!(parse -> Self, map!(
212 alt!(
213 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800214 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500215 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400216 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800217 lifetimes.empty_or_trailing(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500218 Punctuated::<TypeParam, Token![,]>::parse_terminated
Michael Layzell92639a52017-06-01 00:07:44 -0400219 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800220 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400221 (lifetimes, ty_params, Some(lt), Some(gt))
222 )
223 |
David Tolnayf2cfd722017-12-31 18:02:51 -0500224 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
Michael Layzell92639a52017-06-01 00:07:44 -0400225 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700226 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400227 lt_token: lt,
David Tolnay6eff4da2018-01-01 20:27:45 -0800228 params: lifetimes.into_elements()
David Tolnayc2f1aba2017-11-12 20:29:22 -0800229 .map(Element::into_tuple)
David Tolnay660fd1f2017-12-31 01:52:57 -0500230 .map(|(life, comma)| Element::new(GenericParam::Lifetime(life), comma))
David Tolnayc2f1aba2017-11-12 20:29:22 -0800231 .chain(ty_params.unwrap_or_default()
David Tolnay6eff4da2018-01-01 20:27:45 -0800232 .into_elements()
David Tolnayc2f1aba2017-11-12 20:29:22 -0800233 .map(Element::into_tuple)
David Tolnay660fd1f2017-12-31 01:52:57 -0500234 .map(|(ty, comma)| Element::new(GenericParam::Type(ty), comma)))
235 .collect(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800236 gt_token: gt,
David Tolnayac997dd2017-12-27 23:18:22 -0500237 where_clause: None,
Michael Layzell416724e2017-05-24 21:12:34 -0400238 }
Michael Layzell92639a52017-06-01 00:07:44 -0400239 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800240
241 fn description() -> Option<&'static str> {
242 Some("generic parameters in declaration")
243 }
Alex Crichton954046c2017-05-30 21:49:42 -0700244 }
245
Alex Crichton954046c2017-05-30 21:49:42 -0700246 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400247 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500248 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400249 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800250 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400251 bounds: cond!(
252 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500253 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400254 ) >>
255 (LifetimeDef {
256 attrs: attrs,
257 lifetime: life,
258 bounds: bounds.unwrap_or_default(),
David Tolnay6af8f1d2017-12-27 23:08:43 -0500259 colon_token: colon,
Michael Layzell92639a52017-06-01 00:07:44 -0400260 })
261 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800262
263 fn description() -> Option<&'static str> {
264 Some("lifetime definition")
265 }
Alex Crichton954046c2017-05-30 21:49:42 -0700266 }
267
268 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400269 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800270 for_: keyword!(for) >>
271 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500272 lifetimes: call!(Punctuated::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800273 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400274 (BoundLifetimes {
275 for_token: for_,
276 lt_token: lt,
277 gt_token: gt,
278 lifetimes: lifetimes,
279 })
280 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800281
282 fn description() -> Option<&'static str> {
283 Some("bound lifetimes")
284 }
Alex Crichton954046c2017-05-30 21:49:42 -0700285 }
David Tolnay55337722016-09-11 12:58:56 -0700286
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800287 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400288 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500289 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400290 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800291 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400292 bounds: cond!(
293 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500294 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400295 ) >>
296 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800297 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800298 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400299 (eq, ty)
300 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800301 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400302 attrs: attrs,
303 ident: id,
304 bounds: bounds.unwrap_or_default(),
305 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800306 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400307 default: default.map(|d| d.1),
308 })
309 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800310
311 fn description() -> Option<&'static str> {
312 Some("type parameter")
313 }
Alex Crichton954046c2017-05-30 21:49:42 -0700314 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700315
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800316 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400317 named!(parse -> Self, alt!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800318 syn!(Lifetime) => { TypeParamBound::Lifetime }
Michael Layzell92639a52017-06-01 00:07:44 -0400319 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800320 syn!(TraitBound) => { TypeParamBound::Trait }
Michael Layzell92639a52017-06-01 00:07:44 -0400321 |
David Tolnay40fb8ce2018-01-02 10:53:46 -0800322 parens!(syn!(TraitBound)) => { |bound| TypeParamBound::Trait(bound.1) }
Michael Layzell92639a52017-06-01 00:07:44 -0400323 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700324
325 fn description() -> Option<&'static str> {
Nika Layzellc691cb42017-12-04 13:44:38 -0500326 Some("type parameter bound")
Alex Crichton954046c2017-05-30 21:49:42 -0700327 }
328 }
329
David Tolnay40fb8ce2018-01-02 10:53:46 -0800330 impl Synom for TraitBound {
331 named!(parse -> Self, do_parse!(
332 modifier: syn!(TraitBoundModifier) >>
333 lifetimes: option!(syn!(BoundLifetimes)) >>
334 mut path: syn!(Path) >>
335 parenthesized: option!(cond_reduce!(
336 path.segments.last().unwrap().item().arguments.is_empty(),
337 syn!(ParenthesizedGenericArguments)
338 )) >>
339 ({
340 if let Some(parenthesized) = parenthesized {
341 let parenthesized = PathArguments::Parenthesized(parenthesized);
342 path.segments.last_mut().unwrap().item_mut().arguments = parenthesized;
343 }
344 TraitBound {
345 modifier: modifier,
346 lifetimes: lifetimes,
347 path: path,
348 }
349 })
350 ));
351
352 fn description() -> Option<&'static str> {
353 Some("trait bound")
354 }
355 }
356
357 impl Synom for TraitBoundModifier {
358 named!(parse -> Self, alt!(
359 punct!(?) => { TraitBoundModifier::Maybe }
360 |
361 epsilon!() => { |_| TraitBoundModifier::None }
362 ));
363
364 fn description() -> Option<&'static str> {
365 Some("trait bound modifier")
366 }
367 }
368
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500369 impl Synom for ConstParam {
370 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500371 attrs: many0!(Attribute::parse_outer) >>
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500372 const_: keyword!(const) >>
373 ident: syn!(Ident) >>
374 colon: punct!(:) >>
375 ty: syn!(Type) >>
376 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
David Tolnay78ee5202017-12-04 22:17:54 -0800377 ({
378 let (eq_token, default) = match eq_def {
379 Some((eq_token, default)) => (Some(eq_token), Some(default)),
380 None => (None, None),
381 };
382 ConstParam {
383 attrs: attrs,
384 const_token: const_,
385 ident: ident,
386 colon_token: colon,
387 ty: ty,
388 eq_token: eq_token,
389 default: default,
390 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500391 })
392 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800393
394 fn description() -> Option<&'static str> {
395 Some("generic `const` parameter")
396 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500397 }
398
Alex Crichton954046c2017-05-30 21:49:42 -0700399 impl Synom for WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500400 named!(parse -> Self, do_parse!(
401 where_: keyword!(where) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500402 predicates: call!(Punctuated::parse_terminated) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500403 (WhereClause {
404 predicates: predicates,
405 where_token: where_,
406 })
Michael Layzell92639a52017-06-01 00:07:44 -0400407 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700408
409 fn description() -> Option<&'static str> {
410 Some("where clause")
411 }
412 }
413
414 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400415 named!(parse -> Self, alt!(
416 do_parse!(
417 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800418 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400419 bounds: cond!(
420 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500421 Punctuated::parse_separated
Michael Layzell92639a52017-06-01 00:07:44 -0400422 ) >>
David Tolnayd4add852018-01-01 20:13:24 -0800423 (WherePredicate::Lifetime(PredicateLifetime {
Michael Layzell92639a52017-06-01 00:07:44 -0400424 lifetime: ident,
425 bounds: bounds.unwrap_or_default(),
426 colon_token: colon,
427 }))
428 )
429 |
430 do_parse!(
David Tolnay40fb8ce2018-01-02 10:53:46 -0800431 lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800432 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800433 colon: punct!(:) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500434 bounds: call!(Punctuated::parse_separated_nonempty) >>
David Tolnayd4add852018-01-01 20:13:24 -0800435 (WherePredicate::Type(PredicateType {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800436 lifetimes: lifetimes,
Michael Layzell92639a52017-06-01 00:07:44 -0400437 bounded_ty: bounded_ty,
438 bounds: bounds,
439 colon_token: colon,
440 }))
441 )
442 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800443
444 fn description() -> Option<&'static str> {
445 Some("predicate in where clause")
446 }
Alex Crichton954046c2017-05-30 21:49:42 -0700447 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700448}
David Tolnay87d0b442016-09-04 11:52:12 -0700449
450#[cfg(feature = "printing")]
451mod printing {
452 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700453 use attr::FilterAttrs;
David Tolnay51382052017-12-27 13:46:21 -0500454 use quote::{ToTokens, Tokens};
David Tolnay87d0b442016-09-04 11:52:12 -0700455
Michael Layzell3936ceb2017-07-08 00:28:36 -0400456 /// Returns true if the generics object has no lifetimes or ty_params.
457 fn empty_normal_generics(generics: &Generics) -> bool {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800458 generics.params.is_empty()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400459 }
460
David Tolnay8ef93042016-09-04 14:08:40 -0700461 impl ToTokens for Generics {
462 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400463 if empty_normal_generics(self) {
464 return;
465 }
466
Alex Crichton259ee532017-07-14 06:51:02 -0700467 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800468 self.params.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700469 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700470 }
471 }
472
David Tolnaye7678922016-10-13 20:44:03 -0700473 impl<'a> ToTokens for ImplGenerics<'a> {
474 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500475 if empty_normal_generics(self.0) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400476 return;
477 }
478
Alex Crichton259ee532017-07-14 06:51:02 -0700479 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay6eff4da2018-01-01 20:27:45 -0800480 for param in self.0.params.elements() {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800481 match **param.item() {
482 GenericParam::Lifetime(ref param) => {
483 param.to_tokens(tokens);
484 }
485 GenericParam::Type(ref param) => {
486 // Leave off the type parameter defaults
487 tokens.append_all(param.attrs.outer());
488 param.ident.to_tokens(tokens);
489 if !param.bounds.is_empty() {
490 TokensOrDefault(&param.colon_token).to_tokens(tokens);
491 param.bounds.to_tokens(tokens);
492 }
493 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500494 GenericParam::Const(ref param) => {
495 // Leave off the const parameter defaults
496 tokens.append_all(param.attrs.outer());
497 param.const_token.to_tokens(tokens);
498 param.ident.to_tokens(tokens);
499 param.colon_token.to_tokens(tokens);
500 param.ty.to_tokens(tokens);
501 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400502 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500503 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700504 }
Alex Crichton259ee532017-07-14 06:51:02 -0700505 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700506 }
507 }
508
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800509 impl<'a> ToTokens for TypeGenerics<'a> {
David Tolnaye7678922016-10-13 20:44:03 -0700510 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500511 if empty_normal_generics(self.0) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400512 return;
513 }
514
Alex Crichton259ee532017-07-14 06:51:02 -0700515 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnay6eff4da2018-01-01 20:27:45 -0800516 for param in self.0.params.elements() {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800517 match **param.item() {
518 GenericParam::Lifetime(ref param) => {
519 // Leave off the lifetime bounds and attributes
520 param.lifetime.to_tokens(tokens);
521 }
522 GenericParam::Type(ref param) => {
523 // Leave off the type parameter defaults
524 param.ident.to_tokens(tokens);
525 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500526 GenericParam::Const(ref param) => {
527 // Leave off the const parameter defaults
528 param.ident.to_tokens(tokens);
529 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800530 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500531 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700532 }
Alex Crichton259ee532017-07-14 06:51:02 -0700533 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700534 }
535 }
536
David Tolnayc879a502017-01-25 15:51:32 -0800537 impl<'a> ToTokens for Turbofish<'a> {
538 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500539 if !empty_normal_generics(self.0) {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800540 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800541 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800542 }
543 }
544 }
545
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700546 impl ToTokens for BoundLifetimes {
547 fn to_tokens(&self, tokens: &mut Tokens) {
548 self.for_token.to_tokens(tokens);
549 self.lt_token.to_tokens(tokens);
550 self.lifetimes.to_tokens(tokens);
551 self.gt_token.to_tokens(tokens);
552 }
553 }
554
David Tolnay87d0b442016-09-04 11:52:12 -0700555 impl ToTokens for LifetimeDef {
556 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700557 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700558 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400559 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700560 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400561 self.bounds.to_tokens(tokens);
562 }
David Tolnay87d0b442016-09-04 11:52:12 -0700563 }
564 }
565
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800566 impl ToTokens for TypeParam {
David Tolnay8ef93042016-09-04 14:08:40 -0700567 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700568 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700569 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400570 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700571 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400572 self.bounds.to_tokens(tokens);
573 }
574 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700575 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400576 self.default.to_tokens(tokens);
577 }
David Tolnay8ef93042016-09-04 14:08:40 -0700578 }
579 }
580
David Tolnay40fb8ce2018-01-02 10:53:46 -0800581 impl ToTokens for TraitBound {
David Tolnay87d0b442016-09-04 11:52:12 -0700582 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800583 self.modifier.to_tokens(tokens);
584 self.lifetimes.to_tokens(tokens);
585 self.path.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700586 }
587 }
588
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700589 impl ToTokens for TraitBoundModifier {
590 fn to_tokens(&self, tokens: &mut Tokens) {
591 match *self {
592 TraitBoundModifier::None => {}
593 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
594 }
595 }
596 }
597
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500598 impl ToTokens for ConstParam {
599 fn to_tokens(&self, tokens: &mut Tokens) {
600 tokens.append_all(self.attrs.outer());
601 self.const_token.to_tokens(tokens);
602 self.ident.to_tokens(tokens);
603 self.colon_token.to_tokens(tokens);
604 self.ty.to_tokens(tokens);
605 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -0800606 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500607 self.default.to_tokens(tokens);
608 }
609 }
610 }
611
David Tolnay55337722016-09-11 12:58:56 -0700612 impl ToTokens for WhereClause {
613 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnayac997dd2017-12-27 23:18:22 -0500614 self.where_token.to_tokens(tokens);
615 self.predicates.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700616 }
617 }
David Tolnay8ef93042016-09-04 14:08:40 -0700618
David Tolnayd4add852018-01-01 20:13:24 -0800619 impl ToTokens for PredicateType {
David Tolnay8ef93042016-09-04 14:08:40 -0700620 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnay40fb8ce2018-01-02 10:53:46 -0800621 self.lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700622 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700623 self.colon_token.to_tokens(tokens);
624 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700625 }
626 }
627
David Tolnayd4add852018-01-01 20:13:24 -0800628 impl ToTokens for PredicateLifetime {
David Tolnay8ef93042016-09-04 14:08:40 -0700629 fn to_tokens(&self, tokens: &mut Tokens) {
630 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400631 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700632 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400633 self.bounds.to_tokens(tokens);
634 }
David Tolnay8ef93042016-09-04 14:08:40 -0700635 }
636 }
David Tolnayf8e08832017-01-23 00:04:32 -0800637
David Tolnayd4add852018-01-01 20:13:24 -0800638 impl ToTokens for PredicateEq {
David Tolnayf8e08832017-01-23 00:04:32 -0800639 fn to_tokens(&self, tokens: &mut Tokens) {
640 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700641 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -0800642 self.rhs_ty.to_tokens(tokens);
643 }
644 }
David Tolnay87d0b442016-09-04 11:52:12 -0700645}