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