blob: 26c7d3032e8b5480fa09ca6f2e72ab4e88cc053f [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
3use common::word;
4use ty::{ty, poly_trait_ref};
5use nom::multispace as space;
6
7#[derive(Debug, Clone, Eq, PartialEq, Default)]
8pub struct Generics {
9 pub lifetimes: Vec<LifetimeDef>,
10 pub ty_params: Vec<TyParam>,
11 pub where_clause: Vec<WherePredicate>,
12}
13
14#[derive(Debug, Clone, Eq, PartialEq)]
15pub struct Lifetime {
16 pub ident: Ident,
17}
18
19#[derive(Debug, Clone, Eq, PartialEq)]
20pub struct LifetimeDef {
21 pub lifetime: Lifetime,
22 pub bounds: Vec<Lifetime>,
23}
24
25#[derive(Debug, Clone, Eq, PartialEq)]
26pub struct TyParam {
27 pub ident: Ident,
28 pub bounds: Vec<TyParamBound>,
29 pub default: Option<Ty>,
30}
31
32#[derive(Debug, Clone, Eq, PartialEq)]
33pub enum TyParamBound {
34 MaybeSized,
35 Region(Lifetime),
36 Trait(PolyTraitRef),
37}
38
39/// A single predicate in a `where` clause
40#[derive(Debug, Clone, Eq, PartialEq)]
41pub enum WherePredicate {
42 /// A type binding, e.g. `for<'c> Foo: Send+Clone+'c`
43 BoundPredicate(WhereBoundPredicate),
44 /// A lifetime predicate, e.g. `'a: 'b+'c`
45 RegionPredicate(WhereRegionPredicate),
46}
47
48/// A type bound.
49///
50/// E.g. `for<'c> Foo: Send+Clone+'c`
51#[derive(Debug, Clone, Eq, PartialEq)]
52pub struct WhereBoundPredicate {
53 /// Any lifetimes from a `for` binding
54 pub bound_lifetimes: Vec<LifetimeDef>,
55 /// The type being bounded
56 pub bounded_ty: Ty,
57 /// Trait and lifetime bounds (`Clone+Send+'static`)
58 pub bounds: Vec<TyParamBound>,
59}
60
61/// A lifetime predicate.
62///
63/// E.g. `'a: 'b+'c`
64#[derive(Debug, Clone, Eq, PartialEq)]
65pub struct WhereRegionPredicate {
66 pub lifetime: Lifetime,
67 pub bounds: Vec<Lifetime>,
68}
69
70named!(pub generics<&str, Generics>, chain!(
71 bracketed: alt!(
72 chain!(
73 punct!("<") ~
74 lifetimes: separated_list!(punct!(","), lifetime_def) ~
75 ty_params: opt_vec!(preceded!(
76 cond!(!lifetimes.is_empty(), punct!(",")),
77 separated_nonempty_list!(punct!(","), ty_param)
78 )) ~
79 punct!(">"),
80 move || (lifetimes, ty_params)
81 )
82 |
83 epsilon!() => { |_| (Vec::new(), Vec::new()) }
84 ) ~
85 where_clause: opt_vec!(chain!(
86 punct!("where") ~
87 space ~
88 predicates: separated_nonempty_list!(punct!(","), where_predicate) ~
89 punct!(",")? ~
90 move || predicates
91 )),
92 move || Generics {
93 lifetimes: bracketed.0,
94 ty_params: bracketed.1,
95 where_clause: where_clause,
96 }
97));
98
99named!(pub lifetime<&str, Lifetime>, preceded!(
100 punct!("'"),
101 map!(word, |ident| Lifetime { ident: ident })
102));
103
104named!(pub lifetime_def<&str, LifetimeDef>, chain!(
105 life: lifetime ~
106 bounds: opt_vec!(preceded!(
107 punct!(":"),
108 separated_nonempty_list!(punct!(","), lifetime)
109 )),
110 move || LifetimeDef {
111 lifetime: life,
112 bounds: bounds,
113 }
114));
115
116named!(pub bound_lifetimes<&str, Vec<LifetimeDef> >, opt_vec!(chain!(
117 punct!("for") ~
118 punct!("<") ~
119 lifetimes: separated_list!(punct!(","), lifetime_def) ~
120 punct!(">"),
121 move || lifetimes
122)));
123
124named!(ty_param<&str, TyParam>, chain!(
125 ident: word ~
126 bounds: opt_vec!(preceded!(
127 punct!(":"),
128 separated_nonempty_list!(punct!("+"), ty_param_bound)
129 )) ~
130 default: opt!(preceded!(
131 punct!("="),
132 ty
133 )) ~
134 move || TyParam {
135 ident: ident,
136 bounds: bounds,
137 default: default,
138 }
139));
140
141named!(pub ty_param_bound<&str, TyParamBound>, alt!(
142 tuple!(punct!("?"), punct!("Sized")) => { |_| TyParamBound::MaybeSized }
143 |
144 lifetime => { TyParamBound::Region }
145 |
146 poly_trait_ref => { TyParamBound::Trait }
147));
148
149named!(where_predicate<&str, WherePredicate>, alt!(
150 chain!(
151 ident: lifetime ~
152 punct!(":") ~
153 bounds: separated_nonempty_list!(punct!("+"), lifetime),
154 move || WherePredicate::RegionPredicate(WhereRegionPredicate {
155 lifetime: ident,
156 bounds: bounds,
157 })
158 )
159 |
160 chain!(
161 bound_lifetimes: bound_lifetimes ~
162 bounded_ty: ty ~
163 punct!(":") ~
164 bounds: separated_nonempty_list!(punct!("+"), ty_param_bound),
165 move || WherePredicate::BoundPredicate(WhereBoundPredicate {
166 bound_lifetimes: bound_lifetimes,
167 bounded_ty: bounded_ty,
168 bounds: bounds,
169 })
170 )
171));