rustc_builtin_macros/deriving/generic/
ty.rs
1pub(crate) use Ty::*;
5use rustc_ast::ptr::P;
6use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind};
7use rustc_expand::base::ExtCtxt;
8use rustc_span::source_map::respan;
9use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw};
10use thin_vec::ThinVec;
11
12#[derive(Clone)]
15pub(crate) struct Path {
16 path: Vec<Symbol>,
17 params: Vec<Box<Ty>>,
18 kind: PathKind,
19}
20
21#[derive(Clone)]
22pub(crate) enum PathKind {
23 Local,
24 Std,
25}
26
27impl Path {
28 pub(crate) fn new(path: Vec<Symbol>) -> Path {
29 Path::new_(path, Vec::new(), PathKind::Std)
30 }
31 pub(crate) fn new_local(path: Symbol) -> Path {
32 Path::new_(vec![path], Vec::new(), PathKind::Local)
33 }
34 pub(crate) fn new_(path: Vec<Symbol>, params: Vec<Box<Ty>>, kind: PathKind) -> Path {
35 Path { path, params, kind }
36 }
37
38 pub(crate) fn to_ty(
39 &self,
40 cx: &ExtCtxt<'_>,
41 span: Span,
42 self_ty: Ident,
43 self_generics: &Generics,
44 ) -> P<ast::Ty> {
45 cx.ty_path(self.to_path(cx, span, self_ty, self_generics))
46 }
47 pub(crate) fn to_path(
48 &self,
49 cx: &ExtCtxt<'_>,
50 span: Span,
51 self_ty: Ident,
52 self_generics: &Generics,
53 ) -> ast::Path {
54 let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect();
55 let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics));
56 let params = tys.map(GenericArg::Type).collect();
57
58 match self.kind {
59 PathKind::Local => cx.path_all(span, false, idents, params),
60 PathKind::Std => {
61 let def_site = cx.with_def_site_ctxt(DUMMY_SP);
62 idents.insert(0, Ident::new(kw::DollarCrate, def_site));
63 cx.path_all(span, false, idents, params)
64 }
65 }
66 }
67}
68
69#[derive(Clone)]
71pub(crate) enum Ty {
72 Self_,
73 Ref(Box<Ty>, ast::Mutability),
75 Path(Path),
78 Unit,
80}
81
82pub(crate) fn self_ref() -> Ty {
83 Ref(Box::new(Self_), ast::Mutability::Not)
84}
85
86impl Ty {
87 pub(crate) fn to_ty(
88 &self,
89 cx: &ExtCtxt<'_>,
90 span: Span,
91 self_ty: Ident,
92 self_generics: &Generics,
93 ) -> P<ast::Ty> {
94 match self {
95 Ref(ty, mutbl) => {
96 let raw_ty = ty.to_ty(cx, span, self_ty, self_generics);
97 cx.ty_ref(span, raw_ty, None, *mutbl)
98 }
99 Path(p) => p.to_ty(cx, span, self_ty, self_generics),
100 Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)),
101 Unit => {
102 let ty = ast::TyKind::Tup(ThinVec::new());
103 cx.ty(span, ty)
104 }
105 }
106 }
107
108 pub(crate) fn to_path(
109 &self,
110 cx: &ExtCtxt<'_>,
111 span: Span,
112 self_ty: Ident,
113 generics: &Generics,
114 ) -> ast::Path {
115 match self {
116 Self_ => {
117 let params: Vec<_> = generics
118 .params
119 .iter()
120 .map(|param| match param.kind {
121 GenericParamKind::Lifetime { .. } => {
122 GenericArg::Lifetime(ast::Lifetime { id: param.id, ident: param.ident })
123 }
124 GenericParamKind::Type { .. } => {
125 GenericArg::Type(cx.ty_ident(span, param.ident))
126 }
127 GenericParamKind::Const { .. } => {
128 GenericArg::Const(cx.const_ident(span, param.ident))
129 }
130 })
131 .collect();
132
133 cx.path_all(span, false, vec![self_ty], params)
134 }
135 Path(p) => p.to_path(cx, span, self_ty, generics),
136 Ref(..) => cx.dcx().span_bug(span, "ref in a path in generic `derive`"),
137 Unit => cx.dcx().span_bug(span, "unit in a path in generic `derive`"),
138 }
139 }
140}
141
142fn mk_ty_param(
143 cx: &ExtCtxt<'_>,
144 span: Span,
145 name: Symbol,
146 bounds: &[Path],
147 self_ident: Ident,
148 self_generics: &Generics,
149) -> ast::GenericParam {
150 let bounds = bounds
151 .iter()
152 .map(|b| {
153 let path = b.to_path(cx, span, self_ident, self_generics);
154 cx.trait_bound(path, false)
155 })
156 .collect();
157 cx.typaram(span, Ident::new(name, span), bounds, None)
158}
159
160#[derive(Clone)]
162pub(crate) struct Bounds {
163 pub bounds: Vec<(Symbol, Vec<Path>)>,
164}
165
166impl Bounds {
167 pub(crate) fn empty() -> Bounds {
168 Bounds { bounds: Vec::new() }
169 }
170 pub(crate) fn to_generics(
171 &self,
172 cx: &ExtCtxt<'_>,
173 span: Span,
174 self_ty: Ident,
175 self_generics: &Generics,
176 ) -> Generics {
177 let params = self
178 .bounds
179 .iter()
180 .map(|&(name, ref bounds)| mk_ty_param(cx, span, name, bounds, self_ty, self_generics))
181 .collect();
182
183 Generics {
184 params,
185 where_clause: ast::WhereClause {
186 has_where_token: false,
187 predicates: ThinVec::new(),
188 span,
189 },
190 span,
191 }
192 }
193}
194
195pub(crate) fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (P<Expr>, ast::ExplicitSelf) {
196 let self_path = cx.expr_self(span);
198 let self_ty = respan(span, SelfKind::Region(None, ast::Mutability::Not));
199 (self_path, self_ty)
200}