blob: a875422ecab29ae85ecc4b1ab9f86e9377de5115 [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};
David Tolnay65e7f302016-09-04 10:19:25 -07005use nom::{digit, multispace};
David Tolnayb79ee962016-09-04 09:39:20 -07006
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!(
David Tolnayda4049b2016-09-04 10:59:23 -0700190 ty_vec
David Tolnayb79ee962016-09-04 09:39:20 -0700191 |
David Tolnayda4049b2016-09-04 10:59:23 -0700192 ty_fixed_length_vec
David Tolnayb79ee962016-09-04 09:39:20 -0700193 |
David Tolnayda4049b2016-09-04 10:59:23 -0700194 ty_ptr
David Tolnayb79ee962016-09-04 09:39:20 -0700195 |
David Tolnayda4049b2016-09-04 10:59:23 -0700196 ty_rptr
David Tolnayb79ee962016-09-04 09:39:20 -0700197 |
David Tolnayda4049b2016-09-04 10:59:23 -0700198 ty_bare_fn
199 |
200 ty_never
201 |
202 ty_tup
203 |
204 ty_path
205 |
206 ty_qpath
207 |
208 ty_impl_trait
209 |
210 ty_paren
211));
212
213named!(ty_vec<&str, Ty>, do_parse!(
214 punct!("[") >>
215 elem: ty >>
216 punct!("]") >>
217 (Ty::Vec(Box::new(elem)))
218));
219
220named!(ty_fixed_length_vec<&str, Ty>, do_parse!(
221 punct!("[") >>
222 elem: ty >>
223 punct!(";") >>
224 opt!(multispace) >>
225 size: map_res!(digit, str::parse) >>
226 (Ty::FixedLengthVec(Box::new(elem), size))
227));
228
229named!(ty_ptr<&str, Ty>, do_parse!(
230 punct!("*") >>
231 mutability: alt!(
232 punct!("const") => { |_| Mutability::Immutable }
233 |
234 punct!("mut") => { |_| Mutability::Mutable }
235 ) >>
236 target: ty >>
237 (Ty::Ptr(Box::new(MutTy {
238 ty: target,
239 mutability: mutability,
240 })))
241));
242
243named!(ty_rptr<&str, Ty>, do_parse!(
244 punct!("&") >>
245 life: opt!(lifetime) >>
246 mutability: mutability >>
247 target: ty >>
248 (Ty::Rptr(life, Box::new(MutTy {
249 ty: target,
250 mutability: mutability,
251 })))
252));
253
254named!(ty_bare_fn<&str, Ty>, do_parse!(
255 punct!("fn") >>
256 multispace >>
257 lifetimes: opt_vec!(delimited!(
258 punct!("<"),
259 separated_list!(punct!(","), lifetime_def),
260 punct!(">")
261 )) >>
262 punct!("(") >>
263 inputs: separated_list!(punct!(","), fn_arg) >>
264 punct!(")") >>
265 output: opt!(preceded!(
266 punct!("->"),
267 ty
268 )) >>
269 (Ty::BareFn(Box::new(BareFnTy {
270 lifetimes: lifetimes,
271 decl: FnDecl {
272 inputs: inputs,
273 output: match output {
274 Some(ty) => FunctionRetTy::Ty(ty),
275 None => FunctionRetTy::Default,
David Tolnayb79ee962016-09-04 09:39:20 -0700276 },
David Tolnayda4049b2016-09-04 10:59:23 -0700277 },
278 })))
279));
280
281named!(ty_never<&str, Ty>, map!(punct!("!"), |_| Ty::Never));
282
283named!(ty_tup<&str, Ty>, do_parse!(
284 punct!("(") >>
285 elems: separated_list!(punct!(","), ty) >>
286 punct!(")") >>
287 (Ty::Tup(elems))
288));
289
290named!(ty_path<&str, Ty>, map!(path, |p| Ty::Path(None, p)));
291
292named!(ty_qpath<&str, Ty>, do_parse!(
293 punct!("<") >>
294 this: map!(ty, Box::new) >>
295 path: opt!(preceded!(
296 tuple!(punct!("as"), multispace),
297 path
298 )) >>
299 punct!(">") >>
300 punct!("::") >>
301 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
302 ({
303 match path {
304 Some(mut path) => {
305 let pos = path.segments.len();
306 path.segments.extend(rest);
307 Ty::Path(Some(QSelf { ty: this, position: pos }), path)
David Tolnayb79ee962016-09-04 09:39:20 -0700308 }
David Tolnayda4049b2016-09-04 10:59:23 -0700309 None => {
310 Ty::Path(Some(QSelf { ty: this, position: 0 }), Path {
311 global: false,
312 segments: rest,
313 })
314 }
315 }
316 })
317));
318
319named!(ty_impl_trait<&str, Ty>, do_parse!(
320 punct!("impl") >>
321 multispace >>
322 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
323 (Ty::ImplTrait(elem))
324));
325
326named!(ty_paren<&str, Ty>, do_parse!(
327 punct!("(") >>
328 elem: ty >>
329 punct!(")") >>
330 (Ty::Paren(Box::new(elem)))
David Tolnayb79ee962016-09-04 09:39:20 -0700331));
332
333named!(mutability<&str, Mutability>, preceded!(
David Tolnay65e7f302016-09-04 10:19:25 -0700334 opt!(multispace),
David Tolnayb79ee962016-09-04 09:39:20 -0700335 alt!(
David Tolnay65e7f302016-09-04 10:19:25 -0700336 terminated!(tag_s!("mut"), multispace) => { |_| Mutability::Mutable }
David Tolnayb79ee962016-09-04 09:39:20 -0700337 |
338 epsilon!() => { |_| Mutability::Immutable }
339 )
340));
341
David Tolnay6b7aaf02016-09-04 10:39:25 -0700342named!(path<&str, Path>, do_parse!(
343 global: opt!(punct!("::")) >>
344 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
345 (Path {
David Tolnayb79ee962016-09-04 09:39:20 -0700346 global: global.is_some(),
347 segments: segments,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700348 })
David Tolnayb79ee962016-09-04 09:39:20 -0700349));
350
351named!(path_segment<&str, PathSegment>, alt!(
David Tolnay6b7aaf02016-09-04 10:39:25 -0700352 do_parse!(
353 ident: word >>
354 punct!("<") >>
355 lifetimes: separated_list!(punct!(","), lifetime) >>
David Tolnayb79ee962016-09-04 09:39:20 -0700356 types: opt_vec!(preceded!(
357 cond!(!lifetimes.is_empty(), punct!(",")),
358 separated_nonempty_list!(
359 punct!(","),
360 terminated!(ty, not!(peek!(punct!("="))))
361 )
David Tolnay6b7aaf02016-09-04 10:39:25 -0700362 )) >>
David Tolnayb79ee962016-09-04 09:39:20 -0700363 bindings: opt_vec!(preceded!(
364 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
365 separated_nonempty_list!(punct!(","), type_binding)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700366 )) >>
367 punct!(">") >>
368 (PathSegment {
David Tolnayb79ee962016-09-04 09:39:20 -0700369 ident: ident,
370 parameters: PathParameters::AngleBracketed(
371 AngleBracketedParameterData {
372 lifetimes: lifetimes,
373 types: types,
374 bindings: bindings,
375 }
376 ),
David Tolnay6b7aaf02016-09-04 10:39:25 -0700377 })
David Tolnayb79ee962016-09-04 09:39:20 -0700378 )
379 |
380 map!(word, PathSegment::ident)
381));
382
David Tolnay6b7aaf02016-09-04 10:39:25 -0700383named!(type_binding<&str, TypeBinding>, do_parse!(
384 ident: word >>
385 punct!("=") >>
386 ty: ty >>
387 (TypeBinding {
David Tolnayb79ee962016-09-04 09:39:20 -0700388 ident: ident,
389 ty: ty,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700390 })
David Tolnayb79ee962016-09-04 09:39:20 -0700391));
392
David Tolnay6b7aaf02016-09-04 10:39:25 -0700393named!(pub poly_trait_ref<&str, PolyTraitRef>, do_parse!(
394 bound_lifetimes: bound_lifetimes >>
395 trait_ref: path >>
396 (PolyTraitRef {
David Tolnayb79ee962016-09-04 09:39:20 -0700397 bound_lifetimes: bound_lifetimes,
398 trait_ref: trait_ref,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700399 })
David Tolnayb79ee962016-09-04 09:39:20 -0700400));
401
David Tolnay6b7aaf02016-09-04 10:39:25 -0700402named!(fn_arg<&str, Arg>, do_parse!(
403 pat: opt!(terminated!(word, punct!(":"))) >>
404 ty: ty >>
405 (Arg {
David Tolnayb79ee962016-09-04 09:39:20 -0700406 pat: pat,
407 ty: ty,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700408 })
David Tolnayb79ee962016-09-04 09:39:20 -0700409));