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};
19 use syntax::ext::base::ExtCtxt;
20 use syntax::ext::build::AstBuilder;
21 use syntax::codemap::{Span,respan};
22 use syntax::owned_slice::OwnedSlice;
23 use syntax::parse::token::special_idents;
26 /// The types of pointers
27 #[derive(Clone, Eq, PartialEq)]
31 Borrowed(Option<&'a str>, ast::Mutability),
36 /// A path, e.g. `::std::option::Option::<i32>` (global). Has support
37 /// for type parameters and a lifetime.
38 #[derive(Clone, Eq, PartialEq)]
40 pub path: Vec<&'a str> ,
41 pub lifetime: Option<&'a str>,
42 pub params: Vec<Box<Ty<'a>>>,
47 pub fn new<'r>(path: Vec<&'r str> ) -> Path<'r> {
48 Path::new_(path, None, Vec::new(), true)
50 pub fn new_local<'r>(path: &'r str) -> Path<'r> {
51 Path::new_(vec!( path ), None, Vec::new(), false)
53 pub fn new_<'r>(path: Vec<&'r str> ,
54 lifetime: Option<&'r str>,
55 params: Vec<Box<Ty<'r>>>,
70 self_generics: &Generics)
72 cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
78 self_generics: &Generics)
80 let idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
81 let lt = mk_lifetimes(cx, span, &self.lifetime);
82 let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
84 cx.path_all(span, self.global, idents, lt, tys, Vec::new())
88 /// A type. Supports pointers, Self, and literals
89 #[derive(Clone, Eq, PartialEq)]
93 Ptr(Box<Ty<'a>>, PtrTy<'a>),
94 /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
95 /// parameter, and things like `i32`
101 pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
102 Borrowed(None, ast::MutImmutable)
104 pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
105 Ptr(ty, borrowed_ptrty())
108 pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
109 Some(Some(borrowed_ptrty()))
112 pub fn borrowed_self<'r>() -> Ty<'r> {
113 borrowed(Box::new(Self_))
116 pub fn nil_ty<'r>() -> Ty<'r> {
120 fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
122 Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
127 fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
129 Some(ref s) => vec!(cx.lifetime(span, cx.ident_of(*s).name)),
139 self_generics: &Generics)
142 Ptr(ref ty, ref ptr) => {
143 let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
145 Borrowed(ref lt, mutbl) => {
146 let lt = mk_lifetime(cx, span, lt);
147 cx.ty_rptr(span, raw_ty, lt, mutbl)
149 Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl)
152 Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
154 cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
156 Tuple(ref fields) => {
157 let ty = ast::TyTup(fields.iter()
158 .map(|f| f.to_ty(cx, span, self_ty, self_generics))
165 pub fn to_path(&self,
169 self_generics: &Generics)
173 let self_params = self_generics.ty_params.map(|ty_param| {
174 cx.ty_ident(span, ty_param.ident)
176 let lifetimes = self_generics.lifetimes.iter()
180 cx.path_all(span, false, vec!(self_ty), lifetimes,
181 self_params.into_vec(), Vec::new())
184 p.to_path(cx, span, self_ty, self_generics)
186 Ptr(..) => { cx.span_bug(span, "pointer in a path in generic `derive`") }
187 Tuple(..) => { cx.span_bug(span, "tuple in a path in generic `derive`") }
193 fn mk_ty_param(cx: &ExtCtxt,
198 self_generics: &Generics)
201 bounds.iter().map(|b| {
202 let path = b.to_path(cx, span, self_ident, self_generics);
203 cx.typarambound(path)
205 cx.typaram(span, cx.ident_of(name), bounds, None)
208 fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
211 lifetimes: lifetimes,
212 ty_params: OwnedSlice::from_vec(ty_params),
213 where_clause: ast::WhereClause {
214 id: ast::DUMMY_NODE_ID,
215 predicates: Vec::new(),
220 /// Lifetimes and bounds on type parameters
222 pub struct LifetimeBounds<'a> {
223 pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
224 pub bounds: Vec<(&'a str, Vec<Path<'a>>)>,
227 impl<'a> LifetimeBounds<'a> {
228 pub fn empty() -> LifetimeBounds<'a> {
230 lifetimes: Vec::new(), bounds: Vec::new()
233 pub fn to_generics(&self,
237 self_generics: &Generics)
239 let lifetimes = self.lifetimes.iter().map(|&(ref lt, ref bounds)| {
242 |b| cx.lifetime(span, cx.ident_of(*b).name)).collect();
243 cx.lifetime_def(span, cx.ident_of(*lt).name, bounds)
245 let ty_params = self.bounds.iter().map(|t| {
247 (ref name, ref bounds) => {
257 mk_generics(lifetimes, ty_params)
261 pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
262 -> (P<Expr>, ast::ExplicitSelf) {
263 // this constructs a fresh `self` path, which will match the fresh `self` binding
265 let self_path = cx.expr_self(span);
268 (self_path, respan(span, ast::SelfValue(special_idents::self_)))
271 let self_ty = respan(
274 Borrowed(ref lt, mutbl) => {
275 let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
276 ast::SelfRegion(lt, mutbl, special_idents::self_)
278 Raw(_) => cx.span_bug(span, "attempted to use *self in deriving definition")
280 let self_expr = cx.expr_deref(span, self_path);