blob: b364c8e5ce7c41f1896d78d72e8feea13a840839 [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
David Tolnay86eca752016-09-04 11:26:41 -07003#[cfg(feature = "parsing")]
David Tolnayb79ee962016-09-04 09:39:20 -07004use common::word;
David Tolnay86eca752016-09-04 11:26:41 -07005#[cfg(feature = "parsing")]
David Tolnayb79ee962016-09-04 09:39:20 -07006use generics::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes};
David Tolnay86eca752016-09-04 11:26:41 -07007#[cfg(feature = "parsing")]
David Tolnay65e7f302016-09-04 10:19:25 -07008use nom::{digit, multispace};
David Tolnayb79ee962016-09-04 09:39:20 -07009
David Tolnay86eca752016-09-04 11:26:41 -070010#[cfg(feature = "parsing")]
David Tolnayb79ee962016-09-04 09:39:20 -070011use std::str;
12
13#[derive(Debug, Clone, Eq, PartialEq)]
14pub enum Ty {
15 /// A variable-length array (`[T]`)
16 Vec(Box<Ty>),
17 /// A fixed length array (`[T; n]`)
18 FixedLengthVec(Box<Ty>, usize),
19 /// A raw pointer (`*const T` or `*mut T`)
20 Ptr(Box<MutTy>),
21 /// A reference (`&'a T` or `&'a mut T`)
22 Rptr(Option<Lifetime>, Box<MutTy>),
23 /// A bare function (e.g. `fn(usize) -> bool`)
24 BareFn(Box<BareFnTy>),
25 /// The never type (`!`)
26 Never,
27 /// A tuple (`(A, B, C, D, ...)`)
28 Tup(Vec<Ty>),
29 /// A path (`module::module::...::Type`), optionally
30 /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
31 ///
32 /// Type parameters are stored in the Path itself
33 Path(Option<QSelf>, Path),
34 /// Something like `A+B`. Note that `B` must always be a path.
35 ObjectSum(Box<Ty>, Vec<TyParamBound>),
36 /// A type like `for<'a> Foo<&'a Bar>`
37 PolyTraitRef(Vec<TyParamBound>),
38 /// An `impl TraitA+TraitB` type.
39 ImplTrait(Vec<TyParamBound>),
40 /// No-op; kept solely so that we can pretty-print faithfully
41 Paren(Box<Ty>),
42 /// TyKind::Infer means the type should be inferred instead of it having been
43 /// specified. This can appear anywhere in a type.
44 Infer,
45}
46
47#[derive(Debug, Clone, Eq, PartialEq)]
48pub struct MutTy {
49 pub ty: Ty,
50 pub mutability: Mutability,
51}
52
53#[derive(Debug, Clone, Eq, PartialEq)]
54pub enum Mutability {
55 Mutable,
56 Immutable,
57}
58
59#[derive(Debug, Clone, Eq, PartialEq)]
60pub struct Path {
61 pub global: bool,
62 pub segments: Vec<PathSegment>,
63}
64
65/// A segment of a path: an identifier, an optional lifetime, and a set of types.
66///
67/// E.g. `std`, `String` or `Box<T>`
68#[derive(Debug, Clone, Eq, PartialEq)]
69pub struct PathSegment {
70 pub ident: Ident,
71 pub parameters: PathParameters,
72}
73
74impl PathSegment {
75 pub fn ident(ident: Ident) -> Self {
76 PathSegment {
77 ident: ident,
78 parameters: PathParameters::none(),
79 }
80 }
81}
82
83/// Parameters of a path segment.
84///
85/// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
86#[derive(Debug, Clone, Eq, PartialEq)]
87pub enum PathParameters {
88 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
89 AngleBracketed(AngleBracketedParameterData),
90 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
91 Parenthesized(ParenthesizedParameterData),
92}
93
94impl PathParameters {
95 pub fn none() -> Self {
96 PathParameters::AngleBracketed(AngleBracketedParameterData::default())
97 }
98}
99
100/// A path like `Foo<'a, T>`
101#[derive(Debug, Clone, Eq, PartialEq, Default)]
102pub struct AngleBracketedParameterData {
103 /// The lifetime parameters for this path segment.
104 pub lifetimes: Vec<Lifetime>,
105 /// The type parameters for this path segment, if present.
106 pub types: Vec<Ty>,
107 /// Bindings (equality constraints) on associated types, if present.
108 ///
109 /// E.g., `Foo<A=Bar>`.
110 pub bindings: Vec<TypeBinding>,
111}
112
113/// Bind a type to an associated type: `A=Foo`.
114#[derive(Debug, Clone, Eq, PartialEq)]
115pub struct TypeBinding {
116 pub ident: Ident,
117 pub ty: Ty,
118}
119
120/// A path like `Foo(A,B) -> C`
121#[derive(Debug, Clone, Eq, PartialEq)]
122pub struct ParenthesizedParameterData {
123 /// `(A, B)`
124 pub inputs: Vec<Ty>,
125 /// `C`
126 pub output: Option<Ty>,
127}
128
129#[derive(Debug, Clone, Eq, PartialEq)]
130pub struct PolyTraitRef {
131 /// The `'a` in `<'a> Foo<&'a T>`
132 pub bound_lifetimes: Vec<LifetimeDef>,
133 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
134 pub trait_ref: Path,
135}
136
137/// The explicit Self type in a "qualified path". The actual
138/// path, including the trait and the associated item, is stored
139/// separately. `position` represents the index of the associated
140/// item qualified with this Self type.
141///
142/// ```rust,ignore
143/// <Vec<T> as a::b::Trait>::AssociatedItem
144/// ^~~~~ ~~~~~~~~~~~~~~^
145/// ty position = 3
146///
147/// <Vec<T>>::AssociatedItem
148/// ^~~~~ ^
149/// ty position = 0
150/// ```
151#[derive(Debug, Clone, Eq, PartialEq)]
152pub struct QSelf {
153 pub ty: Box<Ty>,
154 pub position: usize
155}
156
157#[derive(Debug, Clone, Eq, PartialEq)]
158pub struct BareFnTy {
159 pub lifetimes: Vec<LifetimeDef>,
160 pub decl: FnDecl
161}
162
163/// Header (not the body) of a function declaration.
164///
165/// E.g. `fn foo(bar: baz)`
166#[derive(Debug, Clone, Eq, PartialEq)]
167pub struct FnDecl {
168 pub inputs: Vec<Arg>,
169 pub output: FunctionRetTy,
170}
171
172/// An argument in a function header.
173///
174/// E.g. `bar: usize` as in `fn foo(bar: usize)`
175#[derive(Debug, Clone, Eq, PartialEq)]
176pub struct Arg {
177 pub pat: Option<Ident>,
178 pub ty: Ty,
179}
180
181#[derive(Debug, Clone, Eq, PartialEq)]
182pub enum FunctionRetTy {
183 /// Return type is not specified.
184 ///
185 /// Functions default to `()` and
186 /// closures default to inference. Span points to where return
187 /// type would be inserted.
188 Default,
189 /// Everything else
190 Ty(Ty),
191}
192
David Tolnay86eca752016-09-04 11:26:41 -0700193#[cfg(feature = "parsing")]
David Tolnayb79ee962016-09-04 09:39:20 -0700194named!(pub ty<&str, Ty>, alt!(
David Tolnayda4049b2016-09-04 10:59:23 -0700195 ty_vec
David Tolnayb79ee962016-09-04 09:39:20 -0700196 |
David Tolnayda4049b2016-09-04 10:59:23 -0700197 ty_fixed_length_vec
David Tolnayb79ee962016-09-04 09:39:20 -0700198 |
David Tolnayda4049b2016-09-04 10:59:23 -0700199 ty_ptr
David Tolnayb79ee962016-09-04 09:39:20 -0700200 |
David Tolnayda4049b2016-09-04 10:59:23 -0700201 ty_rptr
David Tolnayb79ee962016-09-04 09:39:20 -0700202 |
David Tolnayda4049b2016-09-04 10:59:23 -0700203 ty_bare_fn
204 |
205 ty_never
206 |
207 ty_tup
208 |
209 ty_path
210 |
211 ty_qpath
212 |
213 ty_impl_trait
214 |
215 ty_paren
216));
217
David Tolnay86eca752016-09-04 11:26:41 -0700218#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700219named!(ty_vec<&str, Ty>, do_parse!(
220 punct!("[") >>
221 elem: ty >>
222 punct!("]") >>
223 (Ty::Vec(Box::new(elem)))
224));
225
David Tolnay86eca752016-09-04 11:26:41 -0700226#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700227named!(ty_fixed_length_vec<&str, Ty>, do_parse!(
228 punct!("[") >>
229 elem: ty >>
230 punct!(";") >>
231 opt!(multispace) >>
232 size: map_res!(digit, str::parse) >>
233 (Ty::FixedLengthVec(Box::new(elem), size))
234));
235
David Tolnay86eca752016-09-04 11:26:41 -0700236#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700237named!(ty_ptr<&str, Ty>, do_parse!(
238 punct!("*") >>
239 mutability: alt!(
240 punct!("const") => { |_| Mutability::Immutable }
241 |
242 punct!("mut") => { |_| Mutability::Mutable }
243 ) >>
244 target: ty >>
245 (Ty::Ptr(Box::new(MutTy {
246 ty: target,
247 mutability: mutability,
248 })))
249));
250
David Tolnay86eca752016-09-04 11:26:41 -0700251#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700252named!(ty_rptr<&str, Ty>, do_parse!(
253 punct!("&") >>
254 life: opt!(lifetime) >>
255 mutability: mutability >>
256 target: ty >>
257 (Ty::Rptr(life, Box::new(MutTy {
258 ty: target,
259 mutability: mutability,
260 })))
261));
262
David Tolnay86eca752016-09-04 11:26:41 -0700263#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700264named!(ty_bare_fn<&str, Ty>, do_parse!(
265 punct!("fn") >>
266 multispace >>
267 lifetimes: opt_vec!(delimited!(
268 punct!("<"),
269 separated_list!(punct!(","), lifetime_def),
270 punct!(">")
271 )) >>
272 punct!("(") >>
273 inputs: separated_list!(punct!(","), fn_arg) >>
274 punct!(")") >>
275 output: opt!(preceded!(
276 punct!("->"),
277 ty
278 )) >>
279 (Ty::BareFn(Box::new(BareFnTy {
280 lifetimes: lifetimes,
281 decl: FnDecl {
282 inputs: inputs,
283 output: match output {
284 Some(ty) => FunctionRetTy::Ty(ty),
285 None => FunctionRetTy::Default,
David Tolnayb79ee962016-09-04 09:39:20 -0700286 },
David Tolnayda4049b2016-09-04 10:59:23 -0700287 },
288 })))
289));
290
David Tolnay86eca752016-09-04 11:26:41 -0700291#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700292named!(ty_never<&str, Ty>, map!(punct!("!"), |_| Ty::Never));
293
David Tolnay86eca752016-09-04 11:26:41 -0700294#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700295named!(ty_tup<&str, Ty>, do_parse!(
296 punct!("(") >>
297 elems: separated_list!(punct!(","), ty) >>
298 punct!(")") >>
299 (Ty::Tup(elems))
300));
301
David Tolnay86eca752016-09-04 11:26:41 -0700302#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700303named!(ty_path<&str, Ty>, map!(path, |p| Ty::Path(None, p)));
304
David Tolnay86eca752016-09-04 11:26:41 -0700305#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700306named!(ty_qpath<&str, Ty>, do_parse!(
307 punct!("<") >>
308 this: map!(ty, Box::new) >>
309 path: opt!(preceded!(
310 tuple!(punct!("as"), multispace),
311 path
312 )) >>
313 punct!(">") >>
314 punct!("::") >>
315 rest: separated_nonempty_list!(punct!("::"), path_segment) >>
316 ({
317 match path {
318 Some(mut path) => {
319 let pos = path.segments.len();
320 path.segments.extend(rest);
321 Ty::Path(Some(QSelf { ty: this, position: pos }), path)
David Tolnayb79ee962016-09-04 09:39:20 -0700322 }
David Tolnayda4049b2016-09-04 10:59:23 -0700323 None => {
324 Ty::Path(Some(QSelf { ty: this, position: 0 }), Path {
325 global: false,
326 segments: rest,
327 })
328 }
329 }
330 })
331));
332
David Tolnay86eca752016-09-04 11:26:41 -0700333#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700334named!(ty_impl_trait<&str, Ty>, do_parse!(
335 punct!("impl") >>
336 multispace >>
337 elem: separated_nonempty_list!(punct!("+"), ty_param_bound) >>
338 (Ty::ImplTrait(elem))
339));
340
David Tolnay86eca752016-09-04 11:26:41 -0700341#[cfg(feature = "parsing")]
David Tolnayda4049b2016-09-04 10:59:23 -0700342named!(ty_paren<&str, Ty>, do_parse!(
343 punct!("(") >>
344 elem: ty >>
345 punct!(")") >>
346 (Ty::Paren(Box::new(elem)))
David Tolnayb79ee962016-09-04 09:39:20 -0700347));
348
David Tolnay86eca752016-09-04 11:26:41 -0700349#[cfg(feature = "parsing")]
David Tolnayb79ee962016-09-04 09:39:20 -0700350named!(mutability<&str, Mutability>, preceded!(
David Tolnay65e7f302016-09-04 10:19:25 -0700351 opt!(multispace),
David Tolnayb79ee962016-09-04 09:39:20 -0700352 alt!(
David Tolnay65e7f302016-09-04 10:19:25 -0700353 terminated!(tag_s!("mut"), multispace) => { |_| Mutability::Mutable }
David Tolnayb79ee962016-09-04 09:39:20 -0700354 |
355 epsilon!() => { |_| Mutability::Immutable }
356 )
357));
358
David Tolnay86eca752016-09-04 11:26:41 -0700359#[cfg(feature = "parsing")]
David Tolnay6b7aaf02016-09-04 10:39:25 -0700360named!(path<&str, Path>, do_parse!(
361 global: opt!(punct!("::")) >>
362 segments: separated_nonempty_list!(punct!("::"), path_segment) >>
363 (Path {
David Tolnayb79ee962016-09-04 09:39:20 -0700364 global: global.is_some(),
365 segments: segments,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700366 })
David Tolnayb79ee962016-09-04 09:39:20 -0700367));
368
David Tolnay86eca752016-09-04 11:26:41 -0700369#[cfg(feature = "parsing")]
David Tolnayb79ee962016-09-04 09:39:20 -0700370named!(path_segment<&str, PathSegment>, alt!(
David Tolnay6b7aaf02016-09-04 10:39:25 -0700371 do_parse!(
372 ident: word >>
373 punct!("<") >>
374 lifetimes: separated_list!(punct!(","), lifetime) >>
David Tolnayb79ee962016-09-04 09:39:20 -0700375 types: opt_vec!(preceded!(
376 cond!(!lifetimes.is_empty(), punct!(",")),
377 separated_nonempty_list!(
378 punct!(","),
379 terminated!(ty, not!(peek!(punct!("="))))
380 )
David Tolnay6b7aaf02016-09-04 10:39:25 -0700381 )) >>
David Tolnayb79ee962016-09-04 09:39:20 -0700382 bindings: opt_vec!(preceded!(
383 cond!(!lifetimes.is_empty() || !types.is_empty(), punct!(",")),
384 separated_nonempty_list!(punct!(","), type_binding)
David Tolnay6b7aaf02016-09-04 10:39:25 -0700385 )) >>
386 punct!(">") >>
387 (PathSegment {
David Tolnayb79ee962016-09-04 09:39:20 -0700388 ident: ident,
389 parameters: PathParameters::AngleBracketed(
390 AngleBracketedParameterData {
391 lifetimes: lifetimes,
392 types: types,
393 bindings: bindings,
394 }
395 ),
David Tolnay6b7aaf02016-09-04 10:39:25 -0700396 })
David Tolnayb79ee962016-09-04 09:39:20 -0700397 )
398 |
399 map!(word, PathSegment::ident)
400));
401
David Tolnay86eca752016-09-04 11:26:41 -0700402#[cfg(feature = "parsing")]
David Tolnay6b7aaf02016-09-04 10:39:25 -0700403named!(type_binding<&str, TypeBinding>, do_parse!(
404 ident: word >>
405 punct!("=") >>
406 ty: ty >>
407 (TypeBinding {
David Tolnayb79ee962016-09-04 09:39:20 -0700408 ident: ident,
409 ty: ty,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700410 })
David Tolnayb79ee962016-09-04 09:39:20 -0700411));
412
David Tolnay86eca752016-09-04 11:26:41 -0700413#[cfg(feature = "parsing")]
David Tolnay6b7aaf02016-09-04 10:39:25 -0700414named!(pub poly_trait_ref<&str, PolyTraitRef>, do_parse!(
415 bound_lifetimes: bound_lifetimes >>
416 trait_ref: path >>
417 (PolyTraitRef {
David Tolnayb79ee962016-09-04 09:39:20 -0700418 bound_lifetimes: bound_lifetimes,
419 trait_ref: trait_ref,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700420 })
David Tolnayb79ee962016-09-04 09:39:20 -0700421));
422
David Tolnay86eca752016-09-04 11:26:41 -0700423#[cfg(feature = "parsing")]
David Tolnay6b7aaf02016-09-04 10:39:25 -0700424named!(fn_arg<&str, Arg>, do_parse!(
425 pat: opt!(terminated!(word, punct!(":"))) >>
426 ty: ty >>
427 (Arg {
David Tolnayb79ee962016-09-04 09:39:20 -0700428 pat: pat,
429 ty: ty,
David Tolnay6b7aaf02016-09-04 10:39:25 -0700430 })
David Tolnayb79ee962016-09-04 09:39:20 -0700431));