]> git.proxmox.com Git - rustc.git/blame - src/libsyntax_ext/deriving/generic/ty.rs
New upstream version 1.38.0+dfsg1
[rustc.git] / src / libsyntax_ext / deriving / generic / ty.rs
CommitLineData
1a4d82fc
JJ
1//! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use
2//! when specifying impls to be derived.
3
9fa01778
XL
4pub use PtrTy::*;
5pub use Ty::*;
1a4d82fc 6
9fa01778 7use syntax::ast::{self, Expr, GenericParamKind, Generics, Ident, SelfKind, GenericArg};
9cc50fc6 8use syntax::ext::base::ExtCtxt;
b7449926 9use syntax::source_map::{respan, DUMMY_SP};
9cc50fc6 10use syntax::ptr::P;
3157f602 11use syntax_pos::Span;
dc9dc135 12use syntax_pos::symbol::kw;
1a4d82fc
JJ
13
14/// The types of pointers
8faf50e0 15#[derive(Clone)]
1a4d82fc
JJ
16pub enum PtrTy<'a> {
17 /// &'lifetime mut
18 Borrowed(Option<&'a str>, ast::Mutability),
19 /// *mut
416331ca 20 #[allow(dead_code)]
1a4d82fc
JJ
21 Raw(ast::Mutability),
22}
23
0731742a 24/// A path, e.g., `::std::option::Option::<i32>` (global). Has support
1a4d82fc 25/// for type parameters and a lifetime.
8faf50e0 26#[derive(Clone)]
1a4d82fc 27pub struct Path<'a> {
ff7c6d11
XL
28 path: Vec<&'a str>,
29 lifetime: Option<&'a str>,
30 params: Vec<Box<Ty<'a>>>,
31 kind: PathKind,
32}
33
8faf50e0 34#[derive(Clone)]
ff7c6d11
XL
35pub enum PathKind {
36 Local,
37 Global,
38 Std,
1a4d82fc
JJ
39}
40
41impl<'a> Path<'a> {
416331ca 42 pub fn new(path: Vec<&str>) -> Path<'_> {
ff7c6d11 43 Path::new_(path, None, Vec::new(), PathKind::Std)
1a4d82fc 44 }
416331ca 45 pub fn new_local(path: &str) -> Path<'_> {
ff7c6d11 46 Path::new_(vec![path], None, Vec::new(), PathKind::Local)
1a4d82fc 47 }
9e0c209e 48 pub fn new_<'r>(path: Vec<&'r str>,
1a4d82fc
JJ
49 lifetime: Option<&'r str>,
50 params: Vec<Box<Ty<'r>>>,
ff7c6d11 51 kind: PathKind)
1a4d82fc
JJ
52 -> Path<'r> {
53 Path {
3b2f2976
XL
54 path,
55 lifetime,
56 params,
ff7c6d11 57 kind,
1a4d82fc
JJ
58 }
59 }
60
61 pub fn to_ty(&self,
9fa01778 62 cx: &ExtCtxt<'_>,
1a4d82fc
JJ
63 span: Span,
64 self_ty: Ident,
65 self_generics: &Generics)
66 -> P<ast::Ty> {
67 cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
68 }
69 pub fn to_path(&self,
9fa01778 70 cx: &ExtCtxt<'_>,
1a4d82fc
JJ
71 span: Span,
72 self_ty: Ident,
73 self_generics: &Generics)
74 -> ast::Path {
ff7c6d11 75 let mut idents = self.path.iter().map(|s| cx.ident_of(*s)).collect();
1a4d82fc 76 let lt = mk_lifetimes(cx, span, &self.lifetime);
8faf50e0
XL
77 let tys: Vec<P<ast::Ty>> =
78 self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)).collect();
79 let params = lt.into_iter()
80 .map(|lt| GenericArg::Lifetime(lt))
81 .chain(tys.into_iter().map(|ty| GenericArg::Type(ty)))
82 .collect();
1a4d82fc 83
ff7c6d11 84 match self.kind {
8faf50e0
XL
85 PathKind::Global => cx.path_all(span, true, idents, params, Vec::new()),
86 PathKind::Local => cx.path_all(span, false, idents, params, Vec::new()),
ff7c6d11 87 PathKind::Std => {
416331ca 88 let def_site = DUMMY_SP.apply_mark(cx.current_expansion.id);
dc9dc135 89 idents.insert(0, Ident::new(kw::DollarCrate, def_site));
8faf50e0 90 cx.path_all(span, false, idents, params, Vec::new())
ff7c6d11
XL
91 }
92 }
93
1a4d82fc
JJ
94 }
95}
96
9fa01778 97/// A type. Supports pointers, Self, and literals.
8faf50e0 98#[derive(Clone)]
1a4d82fc 99pub enum Ty<'a> {
85aaf69f 100 Self_,
1a4d82fc
JJ
101 /// &/Box/ Ty
102 Ptr(Box<Ty<'a>>, PtrTy<'a>),
103 /// mod::mod::Type<[lifetime], [Params...]>, including a plain type
85aaf69f 104 /// parameter, and things like `i32`
1a4d82fc
JJ
105 Literal(Path<'a>),
106 /// includes unit
9e0c209e 107 Tuple(Vec<Ty<'a>>),
1a4d82fc
JJ
108}
109
110pub fn borrowed_ptrty<'r>() -> PtrTy<'r> {
7453a54e 111 Borrowed(None, ast::Mutability::Immutable)
1a4d82fc 112}
416331ca 113pub fn borrowed(ty: Box<Ty<'_>>) -> Ty<'_> {
1a4d82fc
JJ
114 Ptr(ty, borrowed_ptrty())
115}
116
117pub fn borrowed_explicit_self<'r>() -> Option<Option<PtrTy<'r>>> {
118 Some(Some(borrowed_ptrty()))
119}
120
121pub fn borrowed_self<'r>() -> Ty<'r> {
d9579d0f 122 borrowed(Box::new(Self_))
1a4d82fc
JJ
123}
124
125pub fn nil_ty<'r>() -> Ty<'r> {
126 Tuple(Vec::new())
127}
128
9fa01778 129fn mk_lifetime(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Option<ast::Lifetime> {
8faf50e0
XL
130 lt.map(|s|
131 cx.lifetime(span, Ident::from_str(s))
132 )
1a4d82fc
JJ
133}
134
9fa01778 135fn mk_lifetimes(cx: &ExtCtxt<'_>, span: Span, lt: &Option<&str>) -> Vec<ast::Lifetime> {
8faf50e0 136 mk_lifetime(cx, span, lt).into_iter().collect()
1a4d82fc
JJ
137}
138
139impl<'a> Ty<'a> {
140 pub fn to_ty(&self,
9fa01778 141 cx: &ExtCtxt<'_>,
1a4d82fc
JJ
142 span: Span,
143 self_ty: Ident,
144 self_generics: &Generics)
145 -> P<ast::Ty> {
146 match *self {
147 Ptr(ref ty, ref ptr) => {
148 let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
149 match *ptr {
150 Borrowed(ref lt, mutbl) => {
151 let lt = mk_lifetime(cx, span, lt);
152 cx.ty_rptr(span, raw_ty, lt, mutbl)
153 }
9e0c209e 154 Raw(mutbl) => cx.ty_ptr(span, raw_ty, mutbl),
1a4d82fc
JJ
155 }
156 }
9e0c209e
SL
157 Literal(ref p) => p.to_ty(cx, span, self_ty, self_generics),
158 Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)),
1a4d82fc 159 Tuple(ref fields) => {
7453a54e 160 let ty = ast::TyKind::Tup(fields.iter()
1a4d82fc
JJ
161 .map(|f| f.to_ty(cx, span, self_ty, self_generics))
162 .collect());
163 cx.ty(span, ty)
164 }
165 }
166 }
167
168 pub fn to_path(&self,
9fa01778 169 cx: &ExtCtxt<'_>,
1a4d82fc
JJ
170 span: Span,
171 self_ty: Ident,
8faf50e0 172 generics: &Generics)
1a4d82fc
JJ
173 -> ast::Path {
174 match *self {
85aaf69f 175 Self_ => {
8faf50e0
XL
176 let params: Vec<_> = generics.params.iter().map(|param| match param.kind {
177 GenericParamKind::Lifetime { .. } => {
178 GenericArg::Lifetime(ast::Lifetime { id: param.id, ident: param.ident })
179 }
180 GenericParamKind::Type { .. } => {
181 GenericArg::Type(cx.ty_ident(span, param.ident))
182 }
9fa01778
XL
183 GenericParamKind::Const { .. } => {
184 GenericArg::Const(cx.const_ident(span, param.ident))
185 }
8faf50e0 186 }).collect();
1a4d82fc 187
8faf50e0 188 cx.path_all(span, false, vec![self_ty], params, vec![])
1a4d82fc 189 }
8faf50e0 190 Literal(ref p) => p.to_path(cx, span, self_ty, generics),
9e0c209e
SL
191 Ptr(..) => cx.span_bug(span, "pointer in a path in generic `derive`"),
192 Tuple(..) => cx.span_bug(span, "tuple in a path in generic `derive`"),
1a4d82fc
JJ
193 }
194 }
195}
196
197
9fa01778 198fn mk_ty_param(cx: &ExtCtxt<'_>,
1a4d82fc
JJ
199 span: Span,
200 name: &str,
c30ab7b3 201 attrs: &[ast::Attribute],
9fa01778 202 bounds: &[Path<'_>],
1a4d82fc
JJ
203 self_ident: Ident,
204 self_generics: &Generics)
8faf50e0 205 -> ast::GenericParam {
9e0c209e
SL
206 let bounds = bounds.iter()
207 .map(|b| {
1a4d82fc 208 let path = b.to_path(cx, span, self_ident, self_generics);
8faf50e0 209 cx.trait_bound(path)
9e0c209e
SL
210 })
211 .collect();
c30ab7b3 212 cx.typaram(span, cx.ident_of(name), attrs.to_owned(), bounds, None)
1a4d82fc
JJ
213}
214
8faf50e0 215fn mk_generics(params: Vec<ast::GenericParam>, span: Span) -> Generics {
1a4d82fc 216 Generics {
ff7c6d11 217 params,
1a4d82fc 218 where_clause: ast::WhereClause {
1a4d82fc 219 predicates: Vec::new(),
3b2f2976 220 span,
1a4d82fc 221 },
3b2f2976 222 span,
1a4d82fc
JJ
223 }
224}
225
226/// Lifetimes and bounds on type parameters
227#[derive(Clone)]
228pub struct LifetimeBounds<'a> {
229 pub lifetimes: Vec<(&'a str, Vec<&'a str>)>,
230 pub bounds: Vec<(&'a str, Vec<Path<'a>>)>,
231}
232
233impl<'a> LifetimeBounds<'a> {
234 pub fn empty() -> LifetimeBounds<'a> {
235 LifetimeBounds {
9e0c209e
SL
236 lifetimes: Vec::new(),
237 bounds: Vec::new(),
1a4d82fc
JJ
238 }
239 }
240 pub fn to_generics(&self,
9fa01778 241 cx: &ExtCtxt<'_>,
1a4d82fc
JJ
242 span: Span,
243 self_ty: Ident,
244 self_generics: &Generics)
245 -> Generics {
ff7c6d11 246 let generic_params = self.lifetimes
9e0c209e 247 .iter()
7cac9316 248 .map(|&(lt, ref bounds)| {
9e0c209e 249 let bounds = bounds.iter()
8faf50e0
XL
250 .map(|b| ast::GenericBound::Outlives(cx.lifetime(span, Ident::from_str(b))));
251 cx.lifetime_def(span, Ident::from_str(lt), vec![], bounds.collect())
9e0c209e 252 })
ff7c6d11
XL
253 .chain(self.bounds
254 .iter()
255 .map(|t| {
256 let (name, ref bounds) = *t;
8faf50e0 257 mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics)
ff7c6d11
XL
258 })
259 )
9e0c209e 260 .collect();
ff7c6d11
XL
261
262 mk_generics(generic_params, span)
1a4d82fc
JJ
263 }
264}
265
9fa01778 266pub fn get_explicit_self(cx: &ExtCtxt<'_>,
9e0c209e 267 span: Span,
9fa01778 268 self_ptr: &Option<PtrTy<'_>>)
9e0c209e 269 -> (P<Expr>, ast::ExplicitSelf) {
3157f602 270 // this constructs a fresh `self` path
1a4d82fc
JJ
271 let self_path = cx.expr_self(span);
272 match *self_ptr {
9e0c209e 273 None => (self_path, respan(span, SelfKind::Value(ast::Mutability::Immutable))),
1a4d82fc 274 Some(ref ptr) => {
9e0c209e
SL
275 let self_ty =
276 respan(span,
277 match *ptr {
278 Borrowed(ref lt, mutbl) => {
7cac9316 279 let lt = lt.map(|s| cx.lifetime(span, Ident::from_str(s)));
9e0c209e
SL
280 SelfKind::Region(lt, mutbl)
281 }
282 Raw(_) => {
283 cx.span_bug(span, "attempted to use *self in deriving definition")
284 }
285 });
1a4d82fc
JJ
286 let self_expr = cx.expr_deref(span, self_path);
287 (self_expr, self_ty)
288 }
289 }
290}