3 /// The different kinds of types recognized by the compiler
4 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
6 /// A variable-length array (`[T]`)
8 /// A fixed length array (`[T; n]`)
9 Array(Box
<Ty
>, ConstExpr
),
10 /// A raw pointer (`*const T` or `*mut T`)
12 /// A reference (`&'a T` or `&'a mut T`)
13 Rptr(Option
<Lifetime
>, Box
<MutTy
>),
14 /// A bare function (e.g. `fn(usize) -> bool`)
15 BareFn(Box
<BareFnTy
>),
16 /// The never type (`!`)
18 /// A tuple (`(A, B, C, D, ...)`)
20 /// A path (`module::module::...::Type`), optionally
21 /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
23 /// Type parameters are stored in the Path itself
24 Path(Option
<QSelf
>, Path
),
25 /// A trait object type `Bound1 + Bound2 + Bound3`
26 /// where `Bound` is a trait or a lifetime.
27 TraitObject(Vec
<TyParamBound
>),
28 /// An `impl Bound1 + Bound2 + Bound3` type
29 /// where `Bound` is a trait or a lifetime.
30 ImplTrait(Vec
<TyParamBound
>),
31 /// No-op; kept solely so that we can pretty-print faithfully
33 /// TyKind::Infer means the type should be inferred instead of it having been
34 /// specified. This can appear anywhere in a type.
36 /// A macro in the type position.
40 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
43 pub mutability
: Mutability
,
46 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
52 /// A "Path" is essentially Rust's notion of a name.
54 /// It's represented as a sequence of identifiers,
55 /// along with a bunch of supporting information.
57 /// E.g. `std::cmp::PartialEq`
58 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
60 /// A `::foo` path, is relative to the crate root rather than current
61 /// module (like paths in an import).
63 /// The segments in the path: the things separated by `::`.
64 pub segments
: Vec
<PathSegment
>,
67 impl<T
> From
<T
> for Path
68 where T
: Into
<PathSegment
>
70 fn from(segment
: T
) -> Self {
73 segments
: vec
![segment
.into()],
78 /// A segment of a path: an identifier, an optional lifetime, and a set of types.
80 /// E.g. `std`, `String` or `Box<T>`
81 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
82 pub struct PathSegment
{
83 /// The identifier portion of this path segment.
85 /// Type/lifetime parameters attached to this path. They come in
86 /// two flavors: `Path<A,B,C>` and `Path(A,B) -> C`. Note that
87 /// this is more than just simple syntactic sugar; the use of
88 /// parens affects the region binding rules, so we preserve the
90 pub parameters
: PathParameters
,
93 impl<T
> From
<T
> for PathSegment
96 fn from(ident
: T
) -> Self {
99 parameters
: PathParameters
::none(),
104 /// Parameters of a path segment.
106 /// E.g. `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`
107 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
108 pub enum PathParameters
{
109 /// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`
110 AngleBracketed(AngleBracketedParameterData
),
111 /// The `(A, B)` and `C` in `Foo(A, B) -> C`
112 Parenthesized(ParenthesizedParameterData
),
115 impl PathParameters
{
116 pub fn none() -> Self {
117 PathParameters
::AngleBracketed(AngleBracketedParameterData
::default())
120 pub fn is_empty(&self) -> bool
{
122 PathParameters
::AngleBracketed(ref bracketed
) => {
123 bracketed
.lifetimes
.is_empty() && bracketed
.types
.is_empty() &&
124 bracketed
.bindings
.is_empty()
126 PathParameters
::Parenthesized(_
) => false,
131 /// A path like `Foo<'a, T>`
132 #[derive(Debug, Clone, Eq, PartialEq, Default, Hash)]
133 pub struct AngleBracketedParameterData
{
134 /// The lifetime parameters for this path segment.
135 pub lifetimes
: Vec
<Lifetime
>,
136 /// The type parameters for this path segment, if present.
138 /// Bindings (equality constraints) on associated types, if present.
140 /// E.g., `Foo<A=Bar>`.
141 pub bindings
: Vec
<TypeBinding
>,
144 /// Bind a type to an associated type: `A=Foo`.
145 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
146 pub struct TypeBinding
{
151 /// A path like `Foo(A,B) -> C`
152 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
153 pub struct ParenthesizedParameterData
{
157 pub output
: Option
<Ty
>,
160 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
161 pub struct PolyTraitRef
{
162 /// The `'a` in `<'a> Foo<&'a T>`
163 pub bound_lifetimes
: Vec
<LifetimeDef
>,
164 /// The `Foo<&'a T>` in `<'a> Foo<&'a T>`
168 /// The explicit Self type in a "qualified path". The actual
169 /// path, including the trait and the associated item, is stored
170 /// separately. `position` represents the index of the associated
171 /// item qualified with this Self type.
174 /// <Vec<T> as a::b::Trait>::AssociatedItem
175 /// ^~~~~ ~~~~~~~~~~~~~~^
178 /// <Vec<T>>::AssociatedItem
182 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
188 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
189 pub struct BareFnTy
{
190 pub unsafety
: Unsafety
,
191 pub abi
: Option
<Abi
>,
192 pub lifetimes
: Vec
<LifetimeDef
>,
193 pub inputs
: Vec
<BareFnArg
>,
194 pub output
: FunctionRetTy
,
198 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
204 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
210 /// An argument in a function type.
212 /// E.g. `bar: usize` as in `fn foo(bar: usize)`
213 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
214 pub struct BareFnArg
{
215 pub name
: Option
<Ident
>,
219 #[derive(Debug, Clone, Eq, PartialEq, Hash)]
220 pub enum FunctionRetTy
{
221 /// Return type is not specified.
223 /// Functions default to `()` and
224 /// closures default to inference. Span points to where return
225 /// type would be inserted.
231 #[cfg(feature = "parsing")]
234 use {TyParamBound, TraitBoundModifier}
;
235 #[cfg(feature = "full")]
237 #[cfg(feature = "full")]
238 use constant
::parsing
::const_expr
;
239 #[cfg(feature = "full")]
240 use expr
::parsing
::expr
;
241 use generics
::parsing
::{lifetime, lifetime_def, ty_param_bound, bound_lifetimes}
;
242 use ident
::parsing
::ident
;
243 use lit
::parsing
::quoted_string
;
244 use mac
::parsing
::mac
;
247 named
!(pub ty
-> Ty
, alt
!(
248 ty_paren
// must be before ty_tup
250 ty_mac
// must be before ty_path
252 ty_path
// must be before ty_poly_trait_ref
273 named
!(ty_mac
-> Ty
, map
!(mac
, Ty
::Mac
));
275 named
!(ty_vec
-> Ty
, do_parse
!(
279 (Ty
::Slice(Box
::new(elem
)))
282 named
!(ty_array
-> Ty
, do_parse
!(
288 (Ty
::Array(Box
::new(elem
), len
))
291 #[cfg(not(feature = "full"))]
292 use constant
::parsing
::const_expr
as array_len
;
294 #[cfg(feature = "full")]
295 named
!(array_len
-> ConstExpr
, alt
!(
296 terminated
!(const_expr
, after_array_len
)
298 terminated
!(expr
, after_array_len
) => { ConstExpr::Other }
301 #[cfg(feature = "full")]
302 named
!(after_array_len
-> &str, peek
!(punct
!("]")));
304 named
!(ty_ptr
-> Ty
, do_parse
!(
307 keyword
!("const") => { |_| Mutability::Immutable }
309 keyword
!("mut") => { |_| Mutability::Mutable }
312 (Ty
::Ptr(Box
::new(MutTy
{
314 mutability
: mutability
,
318 named
!(ty_rptr
-> Ty
, do_parse
!(
320 life
: option
!(lifetime
) >>
321 mutability
: mutability
>>
323 (Ty
::Rptr(life
, Box
::new(MutTy
{
325 mutability
: mutability
,
329 named
!(ty_bare_fn
-> Ty
, do_parse
!(
330 lifetimes
: opt_vec
!(do_parse
!(
333 lifetimes
: terminated_list
!(punct
!(","), lifetime_def
) >>
337 unsafety
: unsafety
>>
341 inputs
: separated_list
!(punct
!(","), fn_arg
) >>
342 trailing_comma
: option
!(punct
!(",")) >>
343 variadic
: option
!(cond_reduce
!(trailing_comma
.is_some(), punct
!("..."))) >>
345 output
: option
!(preceded
!(
349 (Ty
::BareFn(Box
::new(BareFnTy
{
352 lifetimes
: lifetimes
,
354 output
: match output
{
355 Some(ty
) => FunctionRetTy
::Ty(ty
),
356 None
=> FunctionRetTy
::Default
,
358 variadic
: variadic
.is_some(),
362 named
!(ty_never
-> Ty
, map
!(punct
!("!"), |_
| Ty
::Never
));
364 named
!(ty_tup
-> Ty
, do_parse
!(
366 elems
: terminated_list
!(punct
!(","), ty
) >>
371 named
!(ty_path
-> Ty
, do_parse
!(
373 parenthesized
: cond
!(
374 qpath
.1.segments
.last().unwrap().parameters
== PathParameters
::none(),
375 option
!(parenthesized_parameter_data
)
377 bounds
: many0
!(preceded
!(punct
!("+"), ty_param_bound
)) >>
379 let (qself
, mut path
) = qpath
;
380 if let Some(Some(parenthesized
)) = parenthesized
{
381 path
.segments
.last_mut().unwrap().parameters
= parenthesized
;
383 if bounds
.is_empty() {
384 Ty
::Path(qself
, path
)
386 let path
= TyParamBound
::Trait(
388 bound_lifetimes
: Vec
::new(),
391 TraitBoundModifier
::None
,
393 let bounds
= Some(path
).into_iter().chain(bounds
).collect();
394 Ty
::TraitObject(bounds
)
399 named
!(parenthesized_parameter_data
-> PathParameters
, do_parse
!(
401 inputs
: terminated_list
!(punct
!(","), ty
) >>
403 output
: option
!(preceded
!(
407 (PathParameters
::Parenthesized(
408 ParenthesizedParameterData
{
415 named
!(pub qpath
-> (Option
<QSelf
>, Path
), alt
!(
416 map
!(path
, |p
| (None
, p
))
420 this
: map
!(ty
, Box
::new
) >>
421 path
: option
!(preceded
!(
427 rest
: separated_nonempty_list
!(punct
!("::"), path_segment
) >>
431 let pos
= path
.segments
.len();
432 path
.segments
.extend(rest
);
433 (Some(QSelf { ty: this, position: pos }
), path
)
436 (Some(QSelf { ty: this, position: 0 }
), Path
{
445 map
!(keyword
!("self"), |_
| (None
, "self".into()))
448 named
!(ty_poly_trait_ref
-> Ty
, map
!(
449 separated_nonempty_list
!(punct
!("+"), ty_param_bound
),
453 named
!(ty_impl_trait
-> Ty
, do_parse
!(
455 elem
: separated_nonempty_list
!(punct
!("+"), ty_param_bound
) >>
456 (Ty
::ImplTrait(elem
))
459 named
!(ty_paren
-> Ty
, do_parse
!(
463 (Ty
::Paren(Box
::new(elem
)))
466 named
!(pub mutability
-> Mutability
, alt
!(
467 keyword
!("mut") => { |_| Mutability::Mutable }
469 epsilon
!() => { |_| Mutability::Immutable }
472 named
!(pub path
-> Path
, do_parse
!(
473 global
: option
!(punct
!("::")) >>
474 segments
: separated_nonempty_list
!(punct
!("::"), path_segment
) >>
476 global
: global
.is_some(),
481 named
!(path_segment
-> PathSegment
, alt
!(
483 id
: option
!(ident
) >>
485 lifetimes
: separated_list
!(punct
!(","), lifetime
) >>
486 types
: opt_vec
!(preceded
!(
487 cond
!(!lifetimes
.is_empty(), punct
!(",")),
488 separated_nonempty_list
!(
490 terminated
!(ty
, not
!(punct
!("=")))
493 bindings
: opt_vec
!(preceded
!(
494 cond
!(!lifetimes
.is_empty() || !types
.is_empty(), punct
!(",")),
495 separated_nonempty_list
!(punct
!(","), type_binding
)
497 cond
!(!lifetimes
.is_empty() || !types
.is_empty() || !bindings
.is_empty(), option
!(punct
!(","))) >>
500 ident
: id
.unwrap_or_else(|| "".into()),
501 parameters
: PathParameters
::AngleBracketed(
502 AngleBracketedParameterData
{
503 lifetimes
: lifetimes
,
511 map
!(ident
, Into
::into
)
522 named
!(type_binding
-> TypeBinding
, do_parse
!(
532 named
!(pub poly_trait_ref
-> PolyTraitRef
, do_parse
!(
533 bound_lifetimes
: bound_lifetimes
>>
535 parenthesized
: option
!(cond_reduce
!(
536 trait_ref
.segments
.last().unwrap().parameters
== PathParameters
::none(),
537 parenthesized_parameter_data
540 let mut trait_ref
= trait_ref
;
541 if let Some(parenthesized
) = parenthesized
{
542 trait_ref
.segments
.last_mut().unwrap().parameters
= parenthesized
;
545 bound_lifetimes
: bound_lifetimes
,
546 trait_ref
: trait_ref
,
551 named
!(pub fn_arg
-> BareFnArg
, do_parse
!(
552 name
: option
!(do_parse
!(
555 not
!(tag
!(":")) >> // not ::
565 named
!(pub unsafety
-> Unsafety
, alt
!(
566 keyword
!("unsafe") => { |_| Unsafety::Unsafe }
568 epsilon
!() => { |_| Unsafety::Normal }
571 named
!(pub abi
-> Abi
, do_parse
!(
572 keyword
!("extern") >>
573 name
: option
!(quoted_string
) >>
575 Some(name
) => Abi
::Named(name
),
581 #[cfg(feature = "printing")]
584 use quote
::{Tokens, ToTokens}
;
586 impl ToTokens
for Ty
{
587 fn to_tokens(&self, tokens
: &mut Tokens
) {
589 Ty
::Slice(ref inner
) => {
591 inner
.to_tokens(tokens
);
594 Ty
::Array(ref inner
, ref len
) => {
596 inner
.to_tokens(tokens
);
598 len
.to_tokens(tokens
);
601 Ty
::Ptr(ref target
) => {
603 match target
.mutability
{
604 Mutability
::Mutable
=> tokens
.append("mut"),
605 Mutability
::Immutable
=> tokens
.append("const"),
607 target
.ty
.to_tokens(tokens
);
609 Ty
::Rptr(ref lifetime
, ref target
) => {
611 lifetime
.to_tokens(tokens
);
612 target
.mutability
.to_tokens(tokens
);
613 target
.ty
.to_tokens(tokens
);
615 Ty
::BareFn(ref func
) => {
616 func
.to_tokens(tokens
);
621 Ty
::Tup(ref elems
) => {
623 tokens
.append_separated(elems
, ",");
624 if elems
.len() == 1 {
629 Ty
::Path(None
, ref path
) => {
630 path
.to_tokens(tokens
);
632 Ty
::Path(Some(ref qself
), ref path
) => {
634 qself
.ty
.to_tokens(tokens
);
635 if qself
.position
> 0 {
637 for (i
, segment
) in path
.segments
639 .take(qself
.position
)
641 if i
> 0 || path
.global
{
644 segment
.to_tokens(tokens
);
648 for segment
in path
.segments
.iter().skip(qself
.position
) {
650 segment
.to_tokens(tokens
);
653 Ty
::TraitObject(ref bounds
) => {
654 tokens
.append_separated(bounds
, "+");
656 Ty
::ImplTrait(ref bounds
) => {
657 tokens
.append("impl");
658 tokens
.append_separated(bounds
, "+");
660 Ty
::Paren(ref inner
) => {
662 inner
.to_tokens(tokens
);
668 Ty
::Mac(ref mac
) => mac
.to_tokens(tokens
),
673 impl ToTokens
for Mutability
{
674 fn to_tokens(&self, tokens
: &mut Tokens
) {
675 if let Mutability
::Mutable
= *self {
676 tokens
.append("mut");
681 impl ToTokens
for Path
{
682 fn to_tokens(&self, tokens
: &mut Tokens
) {
683 for (i
, segment
) in self.segments
.iter().enumerate() {
684 if i
> 0 || self.global
{
687 segment
.to_tokens(tokens
);
692 impl ToTokens
for PathSegment
{
693 fn to_tokens(&self, tokens
: &mut Tokens
) {
694 self.ident
.to_tokens(tokens
);
695 if self.ident
.as_ref().is_empty() && self.parameters
.is_empty() {
699 self.parameters
.to_tokens(tokens
);
704 impl ToTokens
for PathParameters
{
705 fn to_tokens(&self, tokens
: &mut Tokens
) {
707 PathParameters
::AngleBracketed(ref parameters
) => {
708 parameters
.to_tokens(tokens
);
710 PathParameters
::Parenthesized(ref parameters
) => {
711 parameters
.to_tokens(tokens
);
717 impl ToTokens
for AngleBracketedParameterData
{
718 fn to_tokens(&self, tokens
: &mut Tokens
) {
719 let has_lifetimes
= !self.lifetimes
.is_empty();
720 let has_types
= !self.types
.is_empty();
721 let has_bindings
= !self.bindings
.is_empty();
722 if !has_lifetimes
&& !has_types
&& !has_bindings
{
728 let mut first
= true;
729 for lifetime
in &self.lifetimes
{
733 lifetime
.to_tokens(tokens
);
736 for ty
in &self.types
{
740 ty
.to_tokens(tokens
);
743 for binding
in &self.bindings
{
747 binding
.to_tokens(tokens
);
755 impl ToTokens
for TypeBinding
{
756 fn to_tokens(&self, tokens
: &mut Tokens
) {
757 self.ident
.to_tokens(tokens
);
759 self.ty
.to_tokens(tokens
);
763 impl ToTokens
for ParenthesizedParameterData
{
764 fn to_tokens(&self, tokens
: &mut Tokens
) {
766 tokens
.append_separated(&self.inputs
, ",");
768 if let Some(ref output
) = self.output
{
770 output
.to_tokens(tokens
);
775 impl ToTokens
for PolyTraitRef
{
776 fn to_tokens(&self, tokens
: &mut Tokens
) {
777 if !self.bound_lifetimes
.is_empty() {
778 tokens
.append("for");
780 tokens
.append_separated(&self.bound_lifetimes
, ",");
783 self.trait_ref
.to_tokens(tokens
);
787 impl ToTokens
for BareFnTy
{
788 fn to_tokens(&self, tokens
: &mut Tokens
) {
789 if !self.lifetimes
.is_empty() {
790 tokens
.append("for");
792 tokens
.append_separated(&self.lifetimes
, ",");
795 self.unsafety
.to_tokens(tokens
);
796 self.abi
.to_tokens(tokens
);
799 tokens
.append_separated(&self.inputs
, ",");
801 if !self.inputs
.is_empty() {
804 tokens
.append("...");
807 if let FunctionRetTy
::Ty(ref ty
) = self.output
{
809 ty
.to_tokens(tokens
);
814 impl ToTokens
for BareFnArg
{
815 fn to_tokens(&self, tokens
: &mut Tokens
) {
816 if let Some(ref name
) = self.name
{
817 name
.to_tokens(tokens
);
820 self.ty
.to_tokens(tokens
);
824 impl ToTokens
for Unsafety
{
825 fn to_tokens(&self, tokens
: &mut Tokens
) {
827 Unsafety
::Unsafe
=> tokens
.append("unsafe"),
828 Unsafety
::Normal
=> {
835 impl ToTokens
for Abi
{
836 fn to_tokens(&self, tokens
: &mut Tokens
) {
837 tokens
.append("extern");
839 Abi
::Named(ref named
) => named
.to_tokens(tokens
),