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