]> git.lizzy.rs Git - rust.git/blob - src/libsyntax_ext/deriving/generic/ty.rs
Rollup merge of #34370 - steveklabnik:keyword-ref-mention, r=Manishearth
[rust.git] / src / libsyntax_ext / deriving / generic / ty.rs
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.
4 //
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.
10
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.
13
14 pub use self::PtrTy::*;
15 pub use self::Ty::*;
16
17 use syntax::ast;
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;
22 use syntax::ptr::P;
23 use syntax_pos::Span;
24
25 /// The types of pointers
26 #[derive(Clone, Eq, PartialEq)]
27 #[allow(dead_code)]
28 pub enum PtrTy<'a> {
29     /// &'lifetime mut
30     Borrowed(Option<&'a str>, ast::Mutability),
31     /// *mut
32     Raw(ast::Mutability),
33 }
34
35 /// A path, e.g. `::std::option::Option::<i32>` (global). Has support
36 /// for type parameters and a lifetime.
37 #[derive(Clone, Eq, PartialEq)]
38 pub struct Path<'a> {
39     pub path: Vec<&'a str> ,
40     pub lifetime: Option<&'a str>,
41     pub params: Vec<Box<Ty<'a>>>,
42     pub global: bool,
43 }
44
45 impl<'a> Path<'a> {
46     pub fn new<'r>(path: Vec<&'r str> ) -> Path<'r> {
47         Path::new_(path, None, Vec::new(), true)
48     }
49     pub fn new_local<'r>(path: &'r str) -> Path<'r> {
50         Path::new_(vec!( path ), None, Vec::new(), false)
51     }
52     pub fn new_<'r>(path: Vec<&'r str> ,
53                     lifetime: Option<&'r str>,
54                     params: Vec<Box<Ty<'r>>>,
55                     global: bool)
56                     -> Path<'r> {
57         Path {
58             path: path,
59             lifetime: lifetime,
60             params: params,
61             global: global
62         }
63     }
64
65     pub fn to_ty(&self,
66                  cx: &ExtCtxt,
67                  span: Span,
68                  self_ty: Ident,
69                  self_generics: &Generics)
70                  -> P<ast::Ty> {
71         cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
72     }
73     pub fn to_path(&self,
74                    cx: &ExtCtxt,
75                    span: Span,
76                    self_ty: Ident,
77                    self_generics: &Generics)
78                    -> ast::Path {
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();
82
83         cx.path_all(span, self.global, idents, lt, tys, Vec::new())
84     }
85 }
86
87 /// A type. Supports pointers, Self, and literals
88 #[derive(Clone, Eq, PartialEq)]
89 pub enum Ty<'a> {
90     Self_,
91     /// &/Box/ Ty
92     Ptr(Box<Ty<'a>>, PtrTy<'a>),
93     /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
94     /// parameter, and things like `i32`
95     Literal(Path<'a>),
96     /// includes unit
97     Tuple(Vec<Ty<'a>> )
98 }
99
100 pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
101     Borrowed(None, ast::Mutability::Immutable)
102 }
103 pub fn borrowed<'r>(ty: Box<Ty<'r>>) -> Ty<'r> {
104     Ptr(ty, borrowed_ptrty())
105 }
106
107 pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
108     Some(Some(borrowed_ptrty()))
109 }
110
111 pub fn borrowed_self<'r>() -> Ty<'r> {
112     borrowed(Box::new(Self_))
113 }
114
115 pub fn nil_ty<'r>() -> Ty<'r> {
116     Tuple(Vec::new())
117 }
118
119 fn mk_lifetime(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
120     match *lt {
121         Some(ref s) => Some(cx.lifetime(span, cx.ident_of(*s).name)),
122         None => None
123     }
124 }
125
126 fn mk_lifetimes(cx: &ExtCtxt, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
127     match *lt {
128         Some(ref s) => vec!(cx.lifetime(span, cx.ident_of(*s).name)),
129         None => vec!()
130     }
131 }
132
133 impl<'a> Ty<'a> {
134     pub fn to_ty(&self,
135                  cx: &ExtCtxt,
136                  span: Span,
137                  self_ty: Ident,
138                  self_generics: &Generics)
139                  -> P<ast::Ty> {
140         match *self {
141             Ptr(ref ty, ref ptr) => {
142                 let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
143                 match *ptr {
144                     Borrowed(ref lt, mutbl) => {
145                         let lt = mk_lifetime(cx, span, lt);
146                         cx.ty_rptr(span, raw_ty, lt, mutbl)
147                     }
148                     Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl)
149                 }
150             }
151             Literal(ref p) => { p.to_ty(cx, span, self_ty, self_generics) }
152             Self_  => {
153                 cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
154             }
155             Tuple(ref fields) => {
156                 let ty = ast::TyKind::Tup(fields.iter()
157                     .map(|f| f.to_ty(cx, span, self_ty, self_generics))
158                     .collect());
159                 cx.ty(span, ty)
160             }
161         }
162     }
163
164     pub fn to_path(&self,
165                    cx: &ExtCtxt,
166                    span: Span,
167                    self_ty: Ident,
168                    self_generics: &Generics)
169                    -> ast::Path {
170         match *self {
171             Self_ => {
172                 let self_params = self_generics.ty_params.iter().map(|ty_param| {
173                     cx.ty_ident(span, ty_param.ident)
174                 }).collect();
175                 let lifetimes = self_generics.lifetimes.iter()
176                                                        .map(|d| d.lifetime)
177                                                        .collect();
178
179                 cx.path_all(span, false, vec![self_ty], lifetimes, self_params, Vec::new())
180             }
181             Literal(ref p) => {
182                 p.to_path(cx, span, self_ty, self_generics)
183             }
184             Ptr(..) => { cx.span_bug(span, "pointer in a path in generic `derive`") }
185             Tuple(..) => { cx.span_bug(span, "tuple in a path in generic `derive`") }
186         }
187     }
188 }
189
190
191 fn mk_ty_param(cx: &ExtCtxt,
192                span: Span,
193                name: &str,
194                bounds: &[Path],
195                self_ident: Ident,
196                self_generics: &Generics)
197                -> ast::TyParam {
198     let bounds =
199         bounds.iter().map(|b| {
200             let path = b.to_path(cx, span, self_ident, self_generics);
201             cx.typarambound(path)
202         }).collect();
203     cx.typaram(span, cx.ident_of(name), bounds, None)
204 }
205
206 fn mk_generics(lifetimes: Vec<ast::LifetimeDef>, ty_params: Vec<ast::TyParam>)
207                -> Generics {
208     Generics {
209         lifetimes: lifetimes,
210         ty_params: P::from_vec(ty_params),
211         where_clause: ast::WhereClause {
212             id: ast::DUMMY_NODE_ID,
213             predicates: Vec::new(),
214         },
215     }
216 }
217
218 /// Lifetimes and bounds on type parameters
219 #[derive(Clone)]
220 pub struct LifetimeBounds<'a> {
221     pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
222     pub bounds: Vec<(&'a str, Vec<Path<'a>>)>,
223 }
224
225 impl<'a> LifetimeBounds<'a> {
226     pub fn empty() -> LifetimeBounds<'a> {
227         LifetimeBounds {
228             lifetimes: Vec::new(), bounds: Vec::new()
229         }
230     }
231     pub fn to_generics(&self,
232                        cx: &ExtCtxt,
233                        span: Span,
234                        self_ty: Ident,
235                        self_generics: &Generics)
236                        -> Generics {
237         let lifetimes = self.lifetimes.iter().map(|&(ref lt, ref bounds)| {
238             let bounds =
239                 bounds.iter().map(
240                     |b| cx.lifetime(span, cx.ident_of(*b).name)).collect();
241             cx.lifetime_def(span, cx.ident_of(*lt).name, bounds)
242         }).collect();
243         let ty_params = self.bounds.iter().map(|t| {
244             match *t {
245                 (ref name, ref bounds) => {
246                     mk_ty_param(cx,
247                                 span,
248                                 *name,
249                                 bounds,
250                                 self_ty,
251                                 self_generics)
252                 }
253             }
254         }).collect();
255         mk_generics(lifetimes, ty_params)
256     }
257 }
258
259 pub fn get_explicit_self(cx: &ExtCtxt, span: Span, self_ptr: &Option<PtrTy>)
260     -> (P<Expr>, ast::ExplicitSelf) {
261     // this constructs a fresh `self` path
262     let self_path = cx.expr_self(span);
263     match *self_ptr {
264         None => {
265             (self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable)))
266         }
267         Some(ref ptr) => {
268             let self_ty = respan(
269                 span,
270                 match *ptr {
271                     Borrowed(ref lt, mutbl) => {
272                         let lt = lt.map(|s| cx.lifetime(span, cx.ident_of(s).name));
273                         SelfKind::Region(lt, mutbl)
274                     }
275                     Raw(_) => cx.span_bug(span, "attempted to use *self in deriving definition")
276                 });
277             let self_expr = cx.expr_deref(span, self_path);
278             (self_expr, self_ty)
279         }
280     }
281 }