1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use
12 //! when specifying impls to be derived.
14 pub use self::PtrTy
::*;
18 use syntax
::ast
::{Expr, Generics, Ident, SelfKind}
;
19 use syntax
::ext
::base
::ExtCtxt
;
20 use syntax
::ext
::build
::AstBuilder
;
21 use syntax
::codemap
::respan
;
25 /// The types of pointers
26 #[derive(Clone, Eq, PartialEq)]
30 Borrowed(Option
<&'a
str>, ast
::Mutability
),
35 /// A path, e.g. `::std::option::Option::<i32>` (global). Has support
36 /// for type parameters and a lifetime.
37 #[derive(Clone, Eq, PartialEq)]
39 pub path
: Vec
<&'a
str>,
40 pub lifetime
: Option
<&'a
str>,
41 pub params
: Vec
<Box
<Ty
<'a
>>>,
46 pub fn new
<'r
>(path
: Vec
<&'r
str>) -> Path
<'r
> {
47 Path
::new_(path
, None
, Vec
::new(), true)
49 pub fn new_local
<'r
>(path
: &'r
str) -> Path
<'r
> {
50 Path
::new_(vec
![path
], None
, Vec
::new(), false)
52 pub fn new_
<'r
>(path
: Vec
<&'r
str>,
53 lifetime
: Option
<&'r
str>,
54 params
: Vec
<Box
<Ty
<'r
>>>,
69 self_generics
: &Generics
)
71 cx
.ty_path(self.to_path(cx
, span
, self_ty
, self_generics
))
77 self_generics
: &Generics
)
79 let idents
= self.path
.iter().map(|s
| cx
.ident_of(*s
)).collect();
80 let lt
= mk_lifetimes(cx
, span
, &self.lifetime
);
81 let tys
= self.params
.iter().map(|t
| t
.to_ty(cx
, span
, self_ty
, self_generics
)).collect();
83 cx
.path_all(span
, self.global
, idents
, lt
, tys
, Vec
::new())
87 /// A type. Supports pointers, Self, and literals
88 #[derive(Clone, Eq, PartialEq)]
92 Ptr(Box
<Ty
<'a
>>, PtrTy
<'a
>),
93 /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
94 /// parameter, and things like `i32`
100 pub fn borrowed_ptrty
<'r
>() -> PtrTy
<'r
> {
101 Borrowed(None
, ast
::Mutability
::Immutable
)
103 pub fn borrowed
<'r
>(ty
: Box
<Ty
<'r
>>) -> Ty
<'r
> {
104 Ptr(ty
, borrowed_ptrty())
107 pub fn borrowed_explicit_self
<'r
>() -> Option
<Option
<PtrTy
<'r
>>> {
108 Some(Some(borrowed_ptrty()))
111 pub fn borrowed_self
<'r
>() -> Ty
<'r
> {
112 borrowed(Box
::new(Self_
))
115 pub fn nil_ty
<'r
>() -> Ty
<'r
> {
119 fn mk_lifetime(cx
: &ExtCtxt
, span
: Span
, lt
: &Option
<&str>) -> Option
<ast
::Lifetime
> {
121 Some(s
) => Some(cx
.lifetime(span
, Ident
::from_str(s
))),
126 fn mk_lifetimes(cx
: &ExtCtxt
, span
: Span
, lt
: &Option
<&str>) -> Vec
<ast
::Lifetime
> {
128 Some(s
) => vec
![cx
.lifetime(span
, Ident
::from_str(s
))],
138 self_generics
: &Generics
)
141 Ptr(ref ty
, ref ptr
) => {
142 let raw_ty
= ty
.to_ty(cx
, span
, self_ty
, self_generics
);
144 Borrowed(ref lt
, mutbl
) => {
145 let lt
= mk_lifetime(cx
, span
, lt
);
146 cx
.ty_rptr(span
, raw_ty
, lt
, mutbl
)
148 Raw(mutbl
) => cx
.ty_ptr(span
, raw_ty
, mutbl
),
151 Literal(ref p
) => p
.to_ty(cx
, span
, self_ty
, self_generics
),
152 Self_
=> cx
.ty_path(self.to_path(cx
, span
, self_ty
, self_generics
)),
153 Tuple(ref fields
) => {
154 let ty
= ast
::TyKind
::Tup(fields
.iter()
155 .map(|f
| f
.to_ty(cx
, span
, self_ty
, self_generics
))
162 pub fn to_path(&self,
166 self_generics
: &Generics
)
170 let self_params
= self_generics
.ty_params
172 .map(|ty_param
| cx
.ty_ident(span
, ty_param
.ident
))
174 let lifetimes
= self_generics
.lifetimes
186 Literal(ref p
) => p
.to_path(cx
, span
, self_ty
, self_generics
),
187 Ptr(..) => cx
.span_bug(span
, "pointer in a path in generic `derive`"),
188 Tuple(..) => cx
.span_bug(span
, "tuple in a path in generic `derive`"),
194 fn mk_ty_param(cx
: &ExtCtxt
,
197 attrs
: &[ast
::Attribute
],
200 self_generics
: &Generics
)
202 let bounds
= bounds
.iter()
204 let path
= b
.to_path(cx
, span
, self_ident
, self_generics
);
205 cx
.typarambound(path
)
208 cx
.typaram(span
, cx
.ident_of(name
), attrs
.to_owned(), bounds
, None
)
211 fn mk_generics(lifetimes
: Vec
<ast
::LifetimeDef
>, ty_params
: Vec
<ast
::TyParam
>, span
: Span
)
214 lifetimes
: lifetimes
,
215 ty_params
: ty_params
,
216 where_clause
: ast
::WhereClause
{
217 id
: ast
::DUMMY_NODE_ID
,
218 predicates
: Vec
::new(),
224 /// Lifetimes and bounds on type parameters
226 pub struct LifetimeBounds
<'a
> {
227 pub lifetimes
: Vec
<(&'a
str, Vec
<&'a
str>)>,
228 pub bounds
: Vec
<(&'a
str, Vec
<Path
<'a
>>)>,
231 impl<'a
> LifetimeBounds
<'a
> {
232 pub fn empty() -> LifetimeBounds
<'a
> {
234 lifetimes
: Vec
::new(),
238 pub fn to_generics(&self,
242 self_generics
: &Generics
)
244 let lifetimes
= self.lifetimes
246 .map(|&(lt
, ref bounds
)| {
247 let bounds
= bounds
.iter()
248 .map(|b
| cx
.lifetime(span
, Ident
::from_str(b
)))
250 cx
.lifetime_def(span
, Ident
::from_str(lt
), vec
![], bounds
)
253 let ty_params
= self.bounds
257 (ref name
, ref bounds
) => {
258 mk_ty_param(cx
, span
, *name
, &[], bounds
, self_ty
, self_generics
)
263 mk_generics(lifetimes
, ty_params
, span
)
267 pub fn get_explicit_self(cx
: &ExtCtxt
,
269 self_ptr
: &Option
<PtrTy
>)
270 -> (P
<Expr
>, ast
::ExplicitSelf
) {
271 // this constructs a fresh `self` path
272 let self_path
= cx
.expr_self(span
);
274 None
=> (self_path
, respan(span
, SelfKind
::Value(ast
::Mutability
::Immutable
))),
279 Borrowed(ref lt
, mutbl
) => {
280 let lt
= lt
.map(|s
| cx
.lifetime(span
, Ident
::from_str(s
)));
281 SelfKind
::Region(lt
, mutbl
)
284 cx
.span_bug(span
, "attempted to use *self in deriving definition")
287 let self_expr
= cx
.expr_deref(span
, self_path
);