blob: 0d28e65ef364cc9e0834b19f7c62ee9598f02b99 [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
3use common::word;
4use generics::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
5use nom::{digit, multispace as space};
6
7use std::str;
8
9#[derive(Debug, Clone, Eq, PartialEq)]
10pub enum Ty {
11 /// A variable-length array (`[T]`)
12 Vec(Box<Ty>),
13 /// A fixed length array (`[T; n]`)
14 FixedLengthVec(Box<Ty>, usize),
15 /// A raw pointer (`*const T` or `*mut T`)
16 Ptr(Box<MutTy>),
17 /// A reference (`&'a T` or `&'a mut T`)
18 Rptr(Option<Lifetime>, Box<MutTy>),
19 /// A bare function (e.g. `fn(usize) -> bool`)
20 BareFn(Box<BareFnTy>),
21 /// The never type (`!`)
22 Never,
23 /// A tuple (`(A, B, C, D, ...)`)
24 Tup(Vec<Ty>),
25 /// A path (`module::module::...::Type`), optionally
26 /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
27 ///
28 /// Type parameters are stored in the Path itself
29 Path(Option<QSelf>, Path),
30 /// Something like `A+B`. Note that `B` must always be a path.
31 ObjectSum(Box<Ty>, Vec<TyParamBound>),
32 /// A type like `for<'a> Foo<&'a Bar>`
33 PolyTraitRef(Vec<TyParamBound>),
34 /// An `impl TraitA+TraitB` type.
35 ImplTrait(Vec<TyParamBound>),
36 /// No-op; kept solely so that we can pretty-print faithfully
37 Paren(Box<Ty>),
38 /// TyKind::Infer means the type should be inferred instead of it having been
39 /// specified. This can appear anywhere in a type.
40 Infer,
41}
42
43#[derive(Debug, Clone, Eq, PartialEq)]
44pub struct MutTy {
45 pub ty: Ty,
46 pub mutability: Mutability,
47}
48
49#[derive(Debug, Clone, Eq, PartialEq)]
50pub enum Mutability {
51 Mutable,
52 Immutable,
53}
54
55#[derive(Debug, Clone, Eq, PartialEq)]
56pub struct Path {
57 pub global: bool,
58 pub segments: Vec<PathSegment>,
59}
60
61/// A segment of a path: an identifier, an optional lifetime, and a set of types.
62///
63/// E.g. `std`, `String` or `Box<T>`
64#[derive(Debug, Clone, Eq, PartialEq)]
65pub struct PathSegment {
66 pub ident: Ident,
67 pub parameters: PathParameters,
68}
69
70impl PathSegment {
71 pub fn ident(ident: Ident) -> Self {
72 PathSegment {
73 ident: ident,
74 parameters: PathParameters::none(),
75 }
76 }
77}
78
79/// Parameters of a path segment.
80///
81/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
82#[derive(Debug, Clone, Eq, PartialEq)]
83pub enum PathParameters {
84 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
85 AngleBracketed(AngleBracketedParameterData),
86 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
87 Parenthesized(ParenthesizedParameterData),
88}
89
90impl PathParameters {
91 pub fn none() -> Self {
92 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
93 }
94}
95
96/// A path like `Foo<'a, T>`
97#[derive(Debug, Clone, Eq, PartialEq, Default)]
98pub struct AngleBracketedParameterData {
99 /// The lifetime parameters for this path segment.
100 pub lifetimes: Vec<Lifetime>,
101 /// The type parameters for this path segment, if present.
102 pub types: Vec<Ty>,
103 /// Bindings (equality constraints) on associated types, if present.
104 ///
105 /// E.g., `Foo<A=Bar>`.
106 pub bindings: Vec<TypeBinding>,
107}
108
109/// Bind a type to an associated type: `A=Foo`.
110#[derive(Debug, Clone, Eq, PartialEq)]
111pub struct TypeBinding {
112 pub ident: Ident,
113 pub ty: Ty,
114}
115
116/// A path like `Foo(A,B) -> C`
117#[derive(Debug, Clone, Eq, PartialEq)]
118pub struct ParenthesizedParameterData {
119 /// `(A, B)`
120 pub inputs: Vec<Ty>,
121 /// `C`
122 pub output: Option<Ty>,
123}
124
125#[derive(Debug, Clone, Eq, PartialEq)]
126pub struct PolyTraitRef {
127 /// The `'a` in `<'a> Foo<&'a T>`
128 pub bound_lifetimes: Vec<LifetimeDef>,
129 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
130 pub trait_ref: Path,
131}
132
133/// The explicit Self type in a "qualified path". The actual
134/// path, including the trait and the associated item, is stored
135/// separately. `position` represents the index of the associated
136/// item qualified with this Self type.
137///
138/// ```rust,ignore
139/// <Vec<T> as a::b::Trait>::AssociatedItem
140/// ^~~~~ ~~~~~~~~~~~~~~^
141/// ty position = 3
142///
143/// <Vec<T>>::AssociatedItem
144/// ^~~~~ ^
145/// ty position = 0
146/// ```
147#[derive(Debug, Clone, Eq, PartialEq)]
148pub struct QSelf {
149 pub ty: Box<Ty>,
150 pub position: usize
151}
152
153#[derive(Debug, Clone, Eq, PartialEq)]
154pub struct BareFnTy {
155 pub lifetimes: Vec<LifetimeDef>,
156 pub decl: FnDecl
157}
158
159/// Header (not the body) of a function declaration.
160///
161/// E.g. `fn foo(bar: baz)`
162#[derive(Debug, Clone, Eq, PartialEq)]
163pub struct FnDecl {
164 pub inputs: Vec<Arg>,
165 pub output: FunctionRetTy,
166}
167
168/// An argument in a function header.
169///
170/// E.g. `bar: usize` as in `fn foo(bar: usize)`
171#[derive(Debug, Clone, Eq, PartialEq)]
172pub struct Arg {
173 pub pat: Option<Ident>,
174 pub ty: Ty,
175}
176
177#[derive(Debug, Clone, Eq, PartialEq)]
178pub enum FunctionRetTy {
179 /// Return type is not specified.
180 ///
181 /// Functions default to `()` and
182 /// closures default to inference. Span points to where return
183 /// type would be inserted.
184 Default,
185 /// Everything else
186 Ty(Ty),
187}
188
189named!(pub ty<&str, Ty>, alt!(
190 delimited!(
191 punct!("["),
192 ty,
193 punct!("]")
194 ) => { |elem| Ty::Vec(Box::new(elem)) }
195 |
196 chain!(
197 punct!("[") ~
198 elem: ty ~
199 punct!(";") ~
200 space? ~
201 size: map_res!(digit, str::parse),
202 move || Ty::FixedLengthVec(Box::new(elem), size)
203 )
204 |
205 chain!(
206 punct!("*") ~
207 mutability: alt!(
208 punct!("const") => { |_| Mutability::Immutable }
209 |
210 punct!("mut") => { |_| Mutability::Mutable }
211 ) ~
212 target: ty,
213 move || Ty::Ptr(Box::new(MutTy {
214 ty: target,
215 mutability: mutability,
216 }))
217 )
218 |
219 chain!(
220 punct!("&") ~
221 life: lifetime? ~
222 mutability: mutability ~
223 target: ty,
224 move || Ty::Rptr(life, Box::new(MutTy {
225 ty: target,
226 mutability: mutability,
227 }))
228 )
229 |
230 chain!(
231 punct!("fn") ~
232 space ~
233 lifetimes: opt_vec!(delimited!(
234 punct!("<"),
235 separated_list!(punct!(","), lifetime_def),
236 punct!(">")
237 )) ~
238 punct!("(") ~
239 inputs: separated_list!(punct!(","), fn_arg) ~
240 punct!(")") ~
241 output: opt!(preceded!(
242 punct!("->"),
243 ty
244 )),
245 move || Ty::BareFn(Box::new(BareFnTy {
246 lifetimes: lifetimes,
247 decl: FnDecl {
248 inputs: inputs,
249 output: match output {
250 Some(ty) => FunctionRetTy::Ty(ty),
251 None => FunctionRetTy::Default,
252 },
253 },
254 }))
255 )
256 |
257 punct!("!") => { |_| Ty::Never }
258 |
259 delimited!(
260 punct!("("),
261 separated_list!(punct!(","), ty),
262 punct!(")")
263 ) => { Ty::Tup }
264 |
265 path => { |p| Ty::Path(None, p) }
266 |
267 chain!(
268 punct!("<") ~
269 this: map!(ty, Box::new) ~
270 path: opt!(preceded!(
271 tuple!(punct!("as"), space),
272 path
273 )) ~
274 punct!(">") ~
275 punct!("::") ~
276 rest: separated_nonempty_list!(punct!("::"), path_segment),
277 move || {
278 match path {
279 Some(mut path) => {
280 let pos = path.segments.len();
281 path.segments.extend(rest);
282 Ty::Path(Some(QSelf { ty: this, position: pos }), path)
283 }
284 None => {
285 Ty::Path(Some(QSelf { ty: this, position: 0 }), Path {
286 global: false,
287 segments: rest,
288 })
289 }
290 }
291 }
292 )
293 |
294 preceded!(
295 tuple!(punct!("impl"), space),
296 separated_nonempty_list!(punct!("+"), ty_param_bound)
297 ) => { Ty::ImplTrait }
298 |
299 delimited!(
300 punct!("("),
301 ty,
302 punct!(")")
303 ) => { |inner| Ty::Paren(Box::new(inner)) }
304));
305
306named!(mutability<&str, Mutability>, preceded!(
307 opt!(space),
308 alt!(
309 terminated!(tag_s!("mut"), space) => { |_| Mutability::Mutable }
310 |
311 epsilon!() => { |_| Mutability::Immutable }
312 )
313));
314
315named!(path<&str, Path>, chain!(
316 global: punct!("::")? ~
317 segments: separated_nonempty_list!(punct!("::"), path_segment),
318 move || Path {
319 global: global.is_some(),
320 segments: segments,
321 }
322));
323
324named!(path_segment<&str, PathSegment>, alt!(
325 chain!(
326 ident: word ~
327 punct!("<") ~
328 lifetimes: separated_list!(punct!(","), lifetime) ~
329 types: opt_vec!(preceded!(
330 cond!(!lifetimes.is_empty(), punct!(",")),
331 separated_nonempty_list!(
332 punct!(","),
333 terminated!(ty, not!(peek!(punct!("="))))
334 )
335 )) ~
336 bindings: opt_vec!(preceded!(
337 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
338 separated_nonempty_list!(punct!(","), type_binding)
339 )) ~
340 punct!(">"),
341 move || PathSegment {
342 ident: ident,
343 parameters: PathParameters::AngleBracketed(
344 AngleBracketedParameterData {
345 lifetimes: lifetimes,
346 types: types,
347 bindings: bindings,
348 }
349 ),
350 }
351 )
352 |
353 map!(word, PathSegment::ident)
354));
355
356named!(type_binding<&str, TypeBinding>, chain!(
357 ident: word ~
358 punct!("=") ~
359 ty: ty,
360 move || TypeBinding {
361 ident: ident,
362 ty: ty,
363 }
364));
365
366named!(pub poly_trait_ref<&str, PolyTraitRef>, chain!(
367 bound_lifetimes: bound_lifetimes ~
368 trait_ref: path,
369 move || PolyTraitRef {
370 bound_lifetimes: bound_lifetimes,
371 trait_ref: trait_ref,
372 }
373));
374
375named!(fn_arg<&str, Arg>, chain!(
376 pat: opt!(terminated!(word, punct!(":"))) ~
377 ty: ty,
378 move || Arg {
379 pat: pat,
380 ty: ty,
381 }
382));