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