blob: 73937194b937565d9a33d1fbe7d34eea4b40b7ed [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!(
190 delimited!(
191 punct!("["),
192 ty,
193 punct!("]")
194 ) => { |elem| Ty::Vec(Box::new(elem)) }
195 |
David Tolnay6b7aaf02016-09-04 10:39:25 -0700196 do_parse!(
197 punct!("[") >>
198 elem: ty >>
199 punct!(";") >>
200 opt!(multispace) >>
201 size: map_res!(digit, str::parse) >>
202 (Ty::FixedLengthVec(Box::new(elem), size))
David Tolnayb79ee962016-09-04 09:39:20 -0700203 )
204 |
David Tolnay6b7aaf02016-09-04 10:39:25 -0700205 do_parse!(
206 punct!("*") >>
David Tolnayb79ee962016-09-04 09:39:20 -0700207 mutability: alt!(
208 punct!("const") => { |_| Mutability::Immutable }
209 |
210 punct!("mut") => { |_| Mutability::Mutable }
David Tolnay6b7aaf02016-09-04 10:39:25 -0700211 ) >>
212 target: ty >>
213 (Ty::Ptr(Box::new(MutTy {
David Tolnayb79ee962016-09-04 09:39:20 -0700214 ty: target,
215 mutability: mutability,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700216 })))
David Tolnayb79ee962016-09-04 09:39:20 -0700217 )
218 |
David Tolnay6b7aaf02016-09-04 10:39:25 -0700219 do_parse!(
220 punct!("&") >>
221 life: opt!(lifetime) >>
222 mutability: mutability >>
223 target: ty >>
224 (Ty::Rptr(life, Box::new(MutTy {
David Tolnayb79ee962016-09-04 09:39:20 -0700225 ty: target,
226 mutability: mutability,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700227 })))
David Tolnayb79ee962016-09-04 09:39:20 -0700228 )
229 |
David Tolnay6b7aaf02016-09-04 10:39:25 -0700230 do_parse!(
231 punct!("fn") >>
232 multispace >>
David Tolnayb79ee962016-09-04 09:39:20 -0700233 lifetimes: opt_vec!(delimited!(
234 punct!("<"),
235 separated_list!(punct!(","), lifetime_def),
236 punct!(">")
David Tolnay6b7aaf02016-09-04 10:39:25 -0700237 )) >>
238 punct!("(") >>
239 inputs: separated_list!(punct!(","), fn_arg) >>
240 punct!(")") >>
David Tolnayb79ee962016-09-04 09:39:20 -0700241 output: opt!(preceded!(
242 punct!("->"),
243 ty
David Tolnay6b7aaf02016-09-04 10:39:25 -0700244 )) >>
245 (Ty::BareFn(Box::new(BareFnTy {
David Tolnayb79ee962016-09-04 09:39:20 -0700246 lifetimes: lifetimes,
247 decl: FnDecl {
248 inputs: inputs,
249 output: match output {
250 Some(ty) => FunctionRetTy::Ty(ty),
251 None => FunctionRetTy::Default,
252 },
253 },
David Tolnay6b7aaf02016-09-04 10:39:25 -0700254 })))
David Tolnayb79ee962016-09-04 09:39:20 -0700255 )
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 |
David Tolnay6b7aaf02016-09-04 10:39:25 -0700267 do_parse!(
268 punct!("<") >>
269 this: map!(ty, Box::new) >>
David Tolnayb79ee962016-09-04 09:39:20 -0700270 path: opt!(preceded!(
David Tolnay65e7f302016-09-04 10:19:25 -0700271 tuple!(punct!("as"), multispace),
David Tolnayb79ee962016-09-04 09:39:20 -0700272 path
David Tolnay6b7aaf02016-09-04 10:39:25 -0700273 )) >>
274 punct!(">") >>
275 punct!("::") >>
276 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
277 ({
David Tolnayb79ee962016-09-04 09:39:20 -0700278 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 }
David Tolnay6b7aaf02016-09-04 10:39:25 -0700291 })
David Tolnayb79ee962016-09-04 09:39:20 -0700292 )
293 |
294 preceded!(
David Tolnay65e7f302016-09-04 10:19:25 -0700295 tuple!(punct!("impl"), multispace),
David Tolnayb79ee962016-09-04 09:39:20 -0700296 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!(
David Tolnay65e7f302016-09-04 10:19:25 -0700307 opt!(multispace),
David Tolnayb79ee962016-09-04 09:39:20 -0700308 alt!(
David Tolnay65e7f302016-09-04 10:19:25 -0700309 terminated!(tag_s!("mut"), multispace) => { |_| Mutability::Mutable }
David Tolnayb79ee962016-09-04 09:39:20 -0700310 |
311 epsilon!() => { |_| Mutability::Immutable }
312 )
313));
314
David Tolnay6b7aaf02016-09-04 10:39:25 -0700315named!(path<&str, Path>, do_parse!(
316 global: opt!(punct!("::")) >>
317 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
318 (Path {
David Tolnayb79ee962016-09-04 09:39:20 -0700319 global: global.is_some(),
320 segments: segments,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700321 })
David Tolnayb79ee962016-09-04 09:39:20 -0700322));
323
324named!(path_segment<&str, PathSegment>, alt!(
David Tolnay6b7aaf02016-09-04 10:39:25 -0700325 do_parse!(
326 ident: word >>
327 punct!("<") >>
328 lifetimes: separated_list!(punct!(","), lifetime) >>
David Tolnayb79ee962016-09-04 09:39:20 -0700329 types: opt_vec!(preceded!(
330 cond!(!lifetimes.is_empty(), punct!(",")),
331 separated_nonempty_list!(
332 punct!(","),
333 terminated!(ty, not!(peek!(punct!("="))))
334 )
David Tolnay6b7aaf02016-09-04 10:39:25 -0700335 )) >>
David Tolnayb79ee962016-09-04 09:39:20 -0700336 bindings: opt_vec!(preceded!(
337 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
338 separated_nonempty_list!(punct!(","), type_binding)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700339 )) >>
340 punct!(">") >>
341 (PathSegment {
David Tolnayb79ee962016-09-04 09:39:20 -0700342 ident: ident,
343 parameters: PathParameters::AngleBracketed(
344 AngleBracketedParameterData {
345 lifetimes: lifetimes,
346 types: types,
347 bindings: bindings,
348 }
349 ),
David Tolnay6b7aaf02016-09-04 10:39:25 -0700350 })
David Tolnayb79ee962016-09-04 09:39:20 -0700351 )
352 |
353 map!(word, PathSegment::ident)
354));
355
David Tolnay6b7aaf02016-09-04 10:39:25 -0700356named!(type_binding<&str, TypeBinding>, do_parse!(
357 ident: word >>
358 punct!("=") >>
359 ty: ty >>
360 (TypeBinding {
David Tolnayb79ee962016-09-04 09:39:20 -0700361 ident: ident,
362 ty: ty,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700363 })
David Tolnayb79ee962016-09-04 09:39:20 -0700364));
365
David Tolnay6b7aaf02016-09-04 10:39:25 -0700366named!(pub poly_trait_ref<&str, PolyTraitRef>, do_parse!(
367 bound_lifetimes: bound_lifetimes >>
368 trait_ref: path >>
369 (PolyTraitRef {
David Tolnayb79ee962016-09-04 09:39:20 -0700370 bound_lifetimes: bound_lifetimes,
371 trait_ref: trait_ref,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700372 })
David Tolnayb79ee962016-09-04 09:39:20 -0700373));
374
David Tolnay6b7aaf02016-09-04 10:39:25 -0700375named!(fn_arg<&str, Arg>, do_parse!(
376 pat: opt!(terminated!(word, punct!(":"))) >>
377 ty: ty >>
378 (Arg {
David Tolnayb79ee962016-09-04 09:39:20 -0700379 pat: pat,
380 ty: ty,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700381 })
David Tolnayb79ee962016-09-04 09:39:20 -0700382));