]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / compiler / rustc_builtin_macros / src / 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
74b04a01 7use rustc_ast::ptr::P;
3dfed10e 8use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
dfeec247
XL
9use rustc_expand::base::ExtCtxt;
10use rustc_span::source_map::{respan, DUMMY_SP};
3dfed10e 11use rustc_span::symbol::{kw, Ident, Symbol};
dfeec247 12use rustc_span::Span;
1a4d82fc
JJ
13
14/// The types of pointers
8faf50e0 15#[derive(Clone)]
e1599b0c 16pub 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
27pub 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
35pub enum PathKind {
36 Local,
37 Global,
38 Std,
1a4d82fc
JJ
39}
40
3dfed10e
XL
41impl 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 93pub 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 104pub fn borrowed_ptrty() -> PtrTy {
dfeec247 105 Borrowed(None, ast::Mutability::Not)
1a4d82fc 106}
3dfed10e 107pub fn borrowed(ty: Box<Ty>) -> Ty {
1a4d82fc
JJ
108 Ptr(ty, borrowed_ptrty())
109}
110
e1599b0c 111pub fn borrowed_explicit_self() -> Option<Option<PtrTy>> {
1a4d82fc
JJ
112 Some(Some(borrowed_ptrty()))
113}
114
3dfed10e 115pub fn borrowed_self() -> Ty {
d9579d0f 116 borrowed(Box::new(Self_))
1a4d82fc
JJ
117}
118
3dfed10e 119pub fn nil_ty() -> Ty {
1a4d82fc
JJ
120 Tuple(Vec::new())
121}
122
e1599b0c
XL
123fn 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 127fn 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 131impl 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
195fn 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 214fn 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
224pub struct Bounds {
225 pub bounds: Vec<(Symbol, Vec<Path>)>,
1a4d82fc
JJ
226}
227
3dfed10e
XL
228impl 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
252pub 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}