blob: 94cadcaa5a3b77385ac1d312baa9a440086f0f70 [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 {
18 /// A lifetime definition, e.g. `'a: 'b+'c+'d`
19 pub Lifetime(LifetimeDef {
20 pub attrs: Vec<Attribute>,
21 pub lifetime: Lifetime,
22 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050023 pub bounds: Punctuated<Lifetime, Token![+]>,
David Tolnayc2f1aba2017-11-12 20:29:22 -080024 }),
25 /// A generic type parameter, e.g. `T: Into<String>`.
26 pub Type(TypeParam {
27 pub attrs: Vec<Attribute>,
28 pub ident: Ident,
29 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -050030 pub bounds: Punctuated<TypeParamBound, Token![+]>,
David Tolnayc2f1aba2017-11-12 20:29:22 -080031 pub eq_token: Option<Token![=]>,
32 pub default: Option<Type>,
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>) {
87 (ImplGenerics(self), TypeGenerics(self), self.where_clause.as_ref())
David Tolnayb153dbc2016-10-04 23:39:10 -070088 }
89}
90
David Tolnaye95cc9f2017-01-25 15:57:09 -080091#[cfg(feature = "printing")]
David Tolnayfd6bf5c2017-11-12 09:41:14 -080092impl<'a> TypeGenerics<'a> {
David Tolnayc879a502017-01-25 15:51:32 -080093 /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
94 pub fn as_turbofish(&self) -> Turbofish {
95 Turbofish(self.0)
96 }
97}
98
Alex Crichton62a0a592017-05-22 13:58:53 -070099ast_struct! {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700100 /// A set of bound lifetimes, e.g. `for<'a, 'b, 'c>`
101 #[derive(Default)]
102 pub struct BoundLifetimes {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800103 pub for_token: Token![for],
104 pub lt_token: Token![<],
David Tolnayf2cfd722017-12-31 18:02:51 -0500105 pub lifetimes: Punctuated<LifetimeDef, Token![,]>,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800106 pub gt_token: Token![>],
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700107 }
108}
109
David Tolnayf9505b52016-10-02 09:18:52 -0700110impl LifetimeDef {
David Tolnay63e3dee2017-06-03 20:13:17 -0700111 pub fn new(lifetime: Lifetime) -> Self {
David Tolnayf9505b52016-10-02 09:18:52 -0700112 LifetimeDef {
David Tolnaye7678922016-10-13 20:44:03 -0700113 attrs: Vec::new(),
David Tolnay63e3dee2017-06-03 20:13:17 -0700114 lifetime: lifetime,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700115 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500116 bounds: Punctuated::new(),
David Tolnayf9505b52016-10-02 09:18:52 -0700117 }
118 }
119}
120
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800121impl From<Ident> for TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700122 fn from(ident: Ident) -> Self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800123 TypeParam {
Ted Driggs0547d0d2017-04-20 10:00:12 -0700124 attrs: vec![],
125 ident: ident,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700126 colon_token: None,
David Tolnayf2cfd722017-12-31 18:02:51 -0500127 bounds: Punctuated::new(),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700128 eq_token: None,
Ted Driggs0547d0d2017-04-20 10:00:12 -0700129 default: None,
130 }
131 }
132}
133
Alex Crichton62a0a592017-05-22 13:58:53 -0700134ast_enum! {
135 /// The AST represents all type param bounds as types.
136 /// `typeck::collect::compute_bounds` matches these against
137 /// the "special" built-in traits (see `middle::lang_items`) and
138 /// detects Copy, Send and Sync.
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800139 pub enum TypeParamBound {
Alex Crichton62a0a592017-05-22 13:58:53 -0700140 Trait(PolyTraitRef, TraitBoundModifier),
141 Region(Lifetime),
142 }
David Tolnay55337722016-09-11 12:58:56 -0700143}
144
Alex Crichton62a0a592017-05-22 13:58:53 -0700145ast_enum! {
146 /// A modifier on a bound, currently this is only used for `?Sized`, where the
147 /// modifier is `Maybe`. Negative bounds should also be handled here.
Alex Crichton2e0229c2017-05-23 09:34:50 -0700148 #[cfg_attr(feature = "clone-impls", derive(Copy))]
Alex Crichton62a0a592017-05-22 13:58:53 -0700149 pub enum TraitBoundModifier {
150 None,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800151 Maybe(Token![?]),
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_struct! {
156 /// A `where` clause in a definition
Alex Crichton62a0a592017-05-22 13:58:53 -0700157 pub struct WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500158 pub where_token: Token![where],
David Tolnayf2cfd722017-12-31 18:02:51 -0500159 pub predicates: Punctuated<WherePredicate, Token![,]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700160 }
David Tolnayb79ee962016-09-04 09:39:20 -0700161}
162
Alex Crichton62a0a592017-05-22 13:58:53 -0700163ast_enum_of_structs! {
164 /// A single predicate in a `where` clause
165 pub enum WherePredicate {
166 /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
167 pub BoundPredicate(WhereBoundPredicate {
168 /// Any lifetimes from a `for` binding
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700169 pub bound_lifetimes: Option<BoundLifetimes>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700170 /// The type being bounded
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800171 pub bounded_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800172 pub colon_token: Token![:],
Alex Crichton62a0a592017-05-22 13:58:53 -0700173 /// Trait and lifetime bounds (`Clone+Send+'static`)
David Tolnayf2cfd722017-12-31 18:02:51 -0500174 pub bounds: Punctuated<TypeParamBound, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700175 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700176
Alex Crichton62a0a592017-05-22 13:58:53 -0700177 /// A lifetime predicate, e.g. `'a: 'b+'c`
178 pub RegionPredicate(WhereRegionPredicate {
179 pub lifetime: Lifetime,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800180 pub colon_token: Option<Token![:]>,
David Tolnayf2cfd722017-12-31 18:02:51 -0500181 pub bounds: Punctuated<Lifetime, Token![+]>,
Alex Crichton62a0a592017-05-22 13:58:53 -0700182 }),
David Tolnayb79ee962016-09-04 09:39:20 -0700183
Alex Crichton62a0a592017-05-22 13:58:53 -0700184 /// An equality predicate (unsupported)
185 pub EqPredicate(WhereEqPredicate {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800186 pub lhs_ty: Type,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800187 pub eq_token: Token![=],
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800188 pub rhs_ty: Type,
Alex Crichton62a0a592017-05-22 13:58:53 -0700189 }),
190 }
David Tolnayf8e08832017-01-23 00:04:32 -0800191}
192
David Tolnay86eca752016-09-04 11:26:41 -0700193#[cfg(feature = "parsing")]
David Tolnay9d8f1972016-09-04 11:58:48 -0700194pub mod parsing {
195 use super::*;
David Tolnay9d8f1972016-09-04 11:58:48 -0700196
David Tolnay63e3dee2017-06-03 20:13:17 -0700197 use synom::Synom;
David Tolnayf2cfd722017-12-31 18:02:51 -0500198 use punctuated::Element;
Alex Crichton954046c2017-05-30 21:49:42 -0700199
200 impl Synom for Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400201 named!(parse -> Self, map!(
202 alt!(
203 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800204 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500205 lifetimes: call!(Punctuated::<LifetimeDef, Token![,]>::parse_terminated) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400206 ty_params: cond!(
David Tolnayc2f1aba2017-11-12 20:29:22 -0800207 lifetimes.empty_or_trailing(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500208 Punctuated::<TypeParam, Token![,]>::parse_terminated
Michael Layzell92639a52017-06-01 00:07:44 -0400209 ) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800210 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400211 (lifetimes, ty_params, Some(lt), Some(gt))
212 )
213 |
David Tolnayf2cfd722017-12-31 18:02:51 -0500214 epsilon!() => { |_| (Punctuated::new(), None, None, None) }
Michael Layzell92639a52017-06-01 00:07:44 -0400215 ),
David Tolnaybc7d7d92017-06-03 20:54:05 -0700216 |(lifetimes, ty_params, lt, gt)| Generics {
Michael Layzell92639a52017-06-01 00:07:44 -0400217 lt_token: lt,
David Tolnayc2f1aba2017-11-12 20:29:22 -0800218 params: lifetimes.into_iter()
219 .map(Element::into_tuple)
David Tolnay660fd1f2017-12-31 01:52:57 -0500220 .map(|(life, comma)| Element::new(GenericParam::Lifetime(life), comma))
David Tolnayc2f1aba2017-11-12 20:29:22 -0800221 .chain(ty_params.unwrap_or_default()
222 .into_iter()
223 .map(Element::into_tuple)
David Tolnay660fd1f2017-12-31 01:52:57 -0500224 .map(|(ty, comma)| Element::new(GenericParam::Type(ty), comma)))
225 .collect(),
David Tolnayc2f1aba2017-11-12 20:29:22 -0800226 gt_token: gt,
David Tolnayac997dd2017-12-27 23:18:22 -0500227 where_clause: None,
Michael Layzell416724e2017-05-24 21:12:34 -0400228 }
Michael Layzell92639a52017-06-01 00:07:44 -0400229 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800230
231 fn description() -> Option<&'static str> {
232 Some("generic parameters in declaration")
233 }
Alex Crichton954046c2017-05-30 21:49:42 -0700234 }
235
Alex Crichton954046c2017-05-30 21:49:42 -0700236 impl Synom for LifetimeDef {
Michael Layzell92639a52017-06-01 00:07:44 -0400237 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500238 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400239 life: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800240 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400241 bounds: cond!(
242 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500243 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400244 ) >>
245 (LifetimeDef {
246 attrs: attrs,
247 lifetime: life,
248 bounds: bounds.unwrap_or_default(),
David Tolnay6af8f1d2017-12-27 23:08:43 -0500249 colon_token: colon,
Michael Layzell92639a52017-06-01 00:07:44 -0400250 })
251 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800252
253 fn description() -> Option<&'static str> {
254 Some("lifetime definition")
255 }
Alex Crichton954046c2017-05-30 21:49:42 -0700256 }
257
258 impl Synom for BoundLifetimes {
Michael Layzell92639a52017-06-01 00:07:44 -0400259 named!(parse -> Self, do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800260 for_: keyword!(for) >>
261 lt: punct!(<) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500262 lifetimes: call!(Punctuated::parse_terminated) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800263 gt: punct!(>) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400264 (BoundLifetimes {
265 for_token: for_,
266 lt_token: lt,
267 gt_token: gt,
268 lifetimes: lifetimes,
269 })
270 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800271
272 fn description() -> Option<&'static str> {
273 Some("bound lifetimes")
274 }
Alex Crichton954046c2017-05-30 21:49:42 -0700275 }
David Tolnay55337722016-09-11 12:58:56 -0700276
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800277 impl Synom for TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400278 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500279 attrs: many0!(Attribute::parse_outer) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400280 id: syn!(Ident) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800281 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400282 bounds: cond!(
283 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500284 Punctuated::parse_separated_nonempty
Michael Layzell92639a52017-06-01 00:07:44 -0400285 ) >>
286 default: option!(do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800287 eq: punct!(=) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800288 ty: syn!(Type) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400289 (eq, ty)
290 )) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800291 (TypeParam {
Michael Layzell92639a52017-06-01 00:07:44 -0400292 attrs: attrs,
293 ident: id,
294 bounds: bounds.unwrap_or_default(),
295 colon_token: colon,
David Tolnayf8db7ba2017-11-11 22:52:16 -0800296 eq_token: default.as_ref().map(|d| Token![=]((d.0).0)),
Michael Layzell92639a52017-06-01 00:07:44 -0400297 default: default.map(|d| d.1),
298 })
299 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800300
301 fn description() -> Option<&'static str> {
302 Some("type parameter")
303 }
Alex Crichton954046c2017-05-30 21:49:42 -0700304 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700305
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800306 impl Synom for TypeParamBound {
Michael Layzell92639a52017-06-01 00:07:44 -0400307 named!(parse -> Self, alt!(
308 do_parse!(
David Tolnayf8db7ba2017-11-11 22:52:16 -0800309 question: punct!(?) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400310 poly: syn!(PolyTraitRef) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800311 (TypeParamBound::Trait(poly, TraitBoundModifier::Maybe(question)))
Michael Layzell92639a52017-06-01 00:07:44 -0400312 )
313 |
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800314 syn!(Lifetime) => { TypeParamBound::Region }
Michael Layzell92639a52017-06-01 00:07:44 -0400315 |
316 syn!(PolyTraitRef) => {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800317 |poly| TypeParamBound::Trait(poly, TraitBoundModifier::None)
Alex Crichton954046c2017-05-30 21:49:42 -0700318 }
David Tolnayd9faf442017-12-25 23:36:05 -0500319 |
320 parens!(syn!(PolyTraitRef)) => {
David Tolnay8875fca2017-12-31 13:52:37 -0500321 |poly| TypeParamBound::Trait(poly.1, TraitBoundModifier::None)
David Tolnayd9faf442017-12-25 23:36:05 -0500322 }
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
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500330 impl Synom for ConstParam {
331 named!(parse -> Self, do_parse!(
David Tolnay2c136452017-12-27 14:13:32 -0500332 attrs: many0!(Attribute::parse_outer) >>
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500333 const_: keyword!(const) >>
334 ident: syn!(Ident) >>
335 colon: punct!(:) >>
336 ty: syn!(Type) >>
337 eq_def: option!(tuple!(punct!(=), syn!(Expr))) >>
David Tolnay78ee5202017-12-04 22:17:54 -0800338 ({
339 let (eq_token, default) = match eq_def {
340 Some((eq_token, default)) => (Some(eq_token), Some(default)),
341 None => (None, None),
342 };
343 ConstParam {
344 attrs: attrs,
345 const_token: const_,
346 ident: ident,
347 colon_token: colon,
348 ty: ty,
349 eq_token: eq_token,
350 default: default,
351 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500352 })
353 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800354
355 fn description() -> Option<&'static str> {
356 Some("generic `const` parameter")
357 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500358 }
359
Alex Crichton954046c2017-05-30 21:49:42 -0700360 impl Synom for WhereClause {
David Tolnayac997dd2017-12-27 23:18:22 -0500361 named!(parse -> Self, do_parse!(
362 where_: keyword!(where) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500363 predicates: call!(Punctuated::parse_terminated) >>
David Tolnayac997dd2017-12-27 23:18:22 -0500364 (WhereClause {
365 predicates: predicates,
366 where_token: where_,
367 })
Michael Layzell92639a52017-06-01 00:07:44 -0400368 ));
Alex Crichton954046c2017-05-30 21:49:42 -0700369
370 fn description() -> Option<&'static str> {
371 Some("where clause")
372 }
373 }
374
375 impl Synom for WherePredicate {
Michael Layzell92639a52017-06-01 00:07:44 -0400376 named!(parse -> Self, alt!(
377 do_parse!(
378 ident: syn!(Lifetime) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800379 colon: option!(punct!(:)) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400380 bounds: cond!(
381 colon.is_some(),
David Tolnayf2cfd722017-12-31 18:02:51 -0500382 Punctuated::parse_separated
Michael Layzell92639a52017-06-01 00:07:44 -0400383 ) >>
384 (WherePredicate::RegionPredicate(WhereRegionPredicate {
385 lifetime: ident,
386 bounds: bounds.unwrap_or_default(),
387 colon_token: colon,
388 }))
389 )
390 |
391 do_parse!(
392 bound_lifetimes: option!(syn!(BoundLifetimes)) >>
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800393 bounded_ty: syn!(Type) >>
David Tolnayf8db7ba2017-11-11 22:52:16 -0800394 colon: punct!(:) >>
David Tolnayf2cfd722017-12-31 18:02:51 -0500395 bounds: call!(Punctuated::parse_separated_nonempty) >>
Michael Layzell92639a52017-06-01 00:07:44 -0400396 (WherePredicate::BoundPredicate(WhereBoundPredicate {
397 bound_lifetimes: bound_lifetimes,
398 bounded_ty: bounded_ty,
399 bounds: bounds,
400 colon_token: colon,
401 }))
402 )
403 ));
Sergio Benitez5680d6a2017-12-29 11:20:29 -0800404
405 fn description() -> Option<&'static str> {
406 Some("predicate in where clause")
407 }
Alex Crichton954046c2017-05-30 21:49:42 -0700408 }
David Tolnay9d8f1972016-09-04 11:58:48 -0700409}
David Tolnay87d0b442016-09-04 11:52:12 -0700410
411#[cfg(feature = "printing")]
412mod printing {
413 use super::*;
David Tolnaye7678922016-10-13 20:44:03 -0700414 use attr::FilterAttrs;
David Tolnay51382052017-12-27 13:46:21 -0500415 use quote::{ToTokens, Tokens};
David Tolnay87d0b442016-09-04 11:52:12 -0700416
Michael Layzell3936ceb2017-07-08 00:28:36 -0400417 /// Returns true if the generics object has no lifetimes or ty_params.
418 fn empty_normal_generics(generics: &Generics) -> bool {
David Tolnayc2f1aba2017-11-12 20:29:22 -0800419 generics.params.is_empty()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400420 }
421
David Tolnay8ef93042016-09-04 14:08:40 -0700422 impl ToTokens for Generics {
423 fn to_tokens(&self, tokens: &mut Tokens) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400424 if empty_normal_generics(self) {
425 return;
426 }
427
Alex Crichton259ee532017-07-14 06:51:02 -0700428 TokensOrDefault(&self.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800429 self.params.to_tokens(tokens);
Alex Crichton259ee532017-07-14 06:51:02 -0700430 TokensOrDefault(&self.gt_token).to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700431 }
432 }
433
David Tolnaye7678922016-10-13 20:44:03 -0700434 impl<'a> ToTokens for ImplGenerics<'a> {
435 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500436 if empty_normal_generics(self.0) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400437 return;
438 }
439
Alex Crichton259ee532017-07-14 06:51:02 -0700440 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800441 for param in self.0.params.iter() {
442 match **param.item() {
443 GenericParam::Lifetime(ref param) => {
444 param.to_tokens(tokens);
445 }
446 GenericParam::Type(ref param) => {
447 // Leave off the type parameter defaults
448 tokens.append_all(param.attrs.outer());
449 param.ident.to_tokens(tokens);
450 if !param.bounds.is_empty() {
451 TokensOrDefault(&param.colon_token).to_tokens(tokens);
452 param.bounds.to_tokens(tokens);
453 }
454 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500455 GenericParam::Const(ref param) => {
456 // Leave off the const parameter defaults
457 tokens.append_all(param.attrs.outer());
458 param.const_token.to_tokens(tokens);
459 param.ident.to_tokens(tokens);
460 param.colon_token.to_tokens(tokens);
461 param.ty.to_tokens(tokens);
462 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400463 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500464 param.punct().to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700465 }
Alex Crichton259ee532017-07-14 06:51:02 -0700466 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700467 }
468 }
469
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800470 impl<'a> ToTokens for TypeGenerics<'a> {
David Tolnaye7678922016-10-13 20:44:03 -0700471 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500472 if empty_normal_generics(self.0) {
Michael Layzell3936ceb2017-07-08 00:28:36 -0400473 return;
474 }
475
Alex Crichton259ee532017-07-14 06:51:02 -0700476 TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
David Tolnayc2f1aba2017-11-12 20:29:22 -0800477 for param in self.0.params.iter() {
478 match **param.item() {
479 GenericParam::Lifetime(ref param) => {
480 // Leave off the lifetime bounds and attributes
481 param.lifetime.to_tokens(tokens);
482 }
483 GenericParam::Type(ref param) => {
484 // Leave off the type parameter defaults
485 param.ident.to_tokens(tokens);
486 }
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500487 GenericParam::Const(ref param) => {
488 // Leave off the const parameter defaults
489 param.ident.to_tokens(tokens);
490 }
David Tolnayc2f1aba2017-11-12 20:29:22 -0800491 }
David Tolnayf2cfd722017-12-31 18:02:51 -0500492 param.punct().to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700493 }
Alex Crichton259ee532017-07-14 06:51:02 -0700494 TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
David Tolnaye7678922016-10-13 20:44:03 -0700495 }
496 }
497
David Tolnayc879a502017-01-25 15:51:32 -0800498 impl<'a> ToTokens for Turbofish<'a> {
499 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500500 if !empty_normal_generics(self.0) {
David Tolnayf8db7ba2017-11-11 22:52:16 -0800501 <Token![::]>::default().to_tokens(tokens);
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800502 TypeGenerics(self.0).to_tokens(tokens);
David Tolnayc879a502017-01-25 15:51:32 -0800503 }
504 }
505 }
506
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700507 impl ToTokens for BoundLifetimes {
508 fn to_tokens(&self, tokens: &mut Tokens) {
509 self.for_token.to_tokens(tokens);
510 self.lt_token.to_tokens(tokens);
511 self.lifetimes.to_tokens(tokens);
512 self.gt_token.to_tokens(tokens);
513 }
514 }
515
David Tolnay87d0b442016-09-04 11:52:12 -0700516 impl ToTokens for LifetimeDef {
517 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700518 tokens.append_all(self.attrs.outer());
David Tolnay87d0b442016-09-04 11:52:12 -0700519 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400520 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700521 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400522 self.bounds.to_tokens(tokens);
523 }
David Tolnay87d0b442016-09-04 11:52:12 -0700524 }
525 }
526
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800527 impl ToTokens for TypeParam {
David Tolnay8ef93042016-09-04 14:08:40 -0700528 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnaye7678922016-10-13 20:44:03 -0700529 tokens.append_all(self.attrs.outer());
David Tolnay8ef93042016-09-04 14:08:40 -0700530 self.ident.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400531 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700532 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400533 self.bounds.to_tokens(tokens);
534 }
535 if self.default.is_some() {
Alex Crichton259ee532017-07-14 06:51:02 -0700536 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400537 self.default.to_tokens(tokens);
538 }
David Tolnay8ef93042016-09-04 14:08:40 -0700539 }
540 }
541
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800542 impl ToTokens for TypeParamBound {
David Tolnay87d0b442016-09-04 11:52:12 -0700543 fn to_tokens(&self, tokens: &mut Tokens) {
544 match *self {
David Tolnayfd6bf5c2017-11-12 09:41:14 -0800545 TypeParamBound::Region(ref lifetime) => lifetime.to_tokens(tokens),
546 TypeParamBound::Trait(ref trait_ref, ref modifier) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700547 modifier.to_tokens(tokens);
David Tolnay55337722016-09-11 12:58:56 -0700548 trait_ref.to_tokens(tokens);
549 }
550 }
551 }
552 }
553
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700554 impl ToTokens for TraitBoundModifier {
555 fn to_tokens(&self, tokens: &mut Tokens) {
556 match *self {
557 TraitBoundModifier::None => {}
558 TraitBoundModifier::Maybe(ref t) => t.to_tokens(tokens),
559 }
560 }
561 }
562
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500563 impl ToTokens for ConstParam {
564 fn to_tokens(&self, tokens: &mut Tokens) {
565 tokens.append_all(self.attrs.outer());
566 self.const_token.to_tokens(tokens);
567 self.ident.to_tokens(tokens);
568 self.colon_token.to_tokens(tokens);
569 self.ty.to_tokens(tokens);
570 if self.default.is_some() {
David Tolnay78ee5202017-12-04 22:17:54 -0800571 TokensOrDefault(&self.eq_token).to_tokens(tokens);
Nika Layzellf1fdc0b2017-12-04 19:58:32 -0500572 self.default.to_tokens(tokens);
573 }
574 }
575 }
576
David Tolnay55337722016-09-11 12:58:56 -0700577 impl ToTokens for WhereClause {
578 fn to_tokens(&self, tokens: &mut Tokens) {
David Tolnayac997dd2017-12-27 23:18:22 -0500579 self.where_token.to_tokens(tokens);
580 self.predicates.to_tokens(tokens);
David Tolnay87d0b442016-09-04 11:52:12 -0700581 }
582 }
David Tolnay8ef93042016-09-04 14:08:40 -0700583
David Tolnay8ef93042016-09-04 14:08:40 -0700584 impl ToTokens for WhereBoundPredicate {
585 fn to_tokens(&self, tokens: &mut Tokens) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700586 self.bound_lifetimes.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700587 self.bounded_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700588 self.colon_token.to_tokens(tokens);
589 self.bounds.to_tokens(tokens);
David Tolnay8ef93042016-09-04 14:08:40 -0700590 }
591 }
592
593 impl ToTokens for WhereRegionPredicate {
594 fn to_tokens(&self, tokens: &mut Tokens) {
595 self.lifetime.to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400596 if !self.bounds.is_empty() {
Alex Crichton259ee532017-07-14 06:51:02 -0700597 TokensOrDefault(&self.colon_token).to_tokens(tokens);
Michael Layzell3936ceb2017-07-08 00:28:36 -0400598 self.bounds.to_tokens(tokens);
599 }
David Tolnay8ef93042016-09-04 14:08:40 -0700600 }
601 }
David Tolnayf8e08832017-01-23 00:04:32 -0800602
603 impl ToTokens for WhereEqPredicate {
604 fn to_tokens(&self, tokens: &mut Tokens) {
605 self.lhs_ty.to_tokens(tokens);
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700606 self.eq_token.to_tokens(tokens);
David Tolnayf8e08832017-01-23 00:04:32 -0800607 self.rhs_ty.to_tokens(tokens);
608 }
609 }
David Tolnay87d0b442016-09-04 11:52:12 -0700610}