]> git.proxmox.com Git - rustc.git/blame - src/librustc_expand/placeholders.rs
New upstream version 1.44.1+dfsg1
[rustc.git] / src / librustc_expand / placeholders.rs
CommitLineData
e74abb32
XL
1use crate::base::ExtCtxt;
2use crate::expand::{AstFragment, AstFragmentKind};
3
74b04a01
XL
4use rustc_ast::ast;
5use rustc_ast::mut_visit::*;
6use rustc_ast::ptr::P;
dfeec247 7use rustc_span::source_map::{dummy_spanned, DUMMY_SP};
9fa01778
XL
8
9use smallvec::{smallvec, SmallVec};
9e0c209e 10
b7449926 11use rustc_data_structures::fx::FxHashMap;
9e0c209e 12
dfeec247
XL
13pub fn placeholder(
14 kind: AstFragmentKind,
15 id: ast::NodeId,
16 vis: Option<ast::Visibility>,
17) -> AstFragment {
ba9703b0
XL
18 fn mac_placeholder() -> ast::MacCall {
19 ast::MacCall {
32a655c1 20 path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
60c5eb7d 21 args: P(ast::MacArgs::Empty),
416331ca 22 prior_type_ascription: None,
e1599b0c 23 }
9e0c209e
SL
24 }
25
dc9dc135 26 let ident = ast::Ident::invalid();
9e0c209e 27 let attrs = Vec::new();
e74abb32 28 let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited));
9e0c209e 29 let span = DUMMY_SP;
dfeec247
XL
30 let expr_placeholder = || {
31 P(ast::Expr {
32 id,
33 span,
34 attrs: ast::AttrVec::new(),
ba9703b0 35 kind: ast::ExprKind::MacCall(mac_placeholder()),
dfeec247
XL
36 })
37 };
ba9703b0
XL
38 let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span });
39 let pat = || P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span });
9e0c209e
SL
40
41 match kind {
8faf50e0
XL
42 AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
43 AstFragmentKind::OptExpr => AstFragment::OptExpr(Some(expr_placeholder())),
b7449926 44 AstFragmentKind::Items => AstFragment::Items(smallvec![P(ast::Item {
dfeec247
XL
45 id,
46 span,
47 ident,
48 vis,
49 attrs,
ba9703b0 50 kind: ast::ItemKind::MacCall(mac_placeholder()),
3b2f2976 51 tokens: None,
b7449926 52 })]),
74b04a01 53 AstFragmentKind::TraitItems => AstFragment::TraitItems(smallvec![P(ast::AssocItem {
dfeec247
XL
54 id,
55 span,
56 ident,
57 vis,
58 attrs,
ba9703b0 59 kind: ast::AssocItemKind::MacCall(mac_placeholder()),
3b2f2976 60 tokens: None,
74b04a01
XL
61 })]),
62 AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem {
dfeec247
XL
63 id,
64 span,
65 ident,
66 vis,
67 attrs,
ba9703b0 68 kind: ast::AssocItemKind::MacCall(mac_placeholder()),
3b2f2976 69 tokens: None,
74b04a01
XL
70 })]),
71 AstFragmentKind::ForeignItems => {
72 AstFragment::ForeignItems(smallvec![P(ast::ForeignItem {
73 id,
74 span,
75 ident,
76 vis,
77 attrs,
ba9703b0 78 kind: ast::ForeignItemKind::MacCall(mac_placeholder()),
74b04a01
XL
79 tokens: None,
80 })])
81 }
ba9703b0
XL
82 AstFragmentKind::Pat => AstFragment::Pat(P(ast::Pat {
83 id,
84 span,
85 kind: ast::PatKind::MacCall(mac_placeholder()),
86 })),
dfeec247 87 AstFragmentKind::Ty => {
ba9703b0 88 AstFragment::Ty(P(ast::Ty { id, span, kind: ast::TyKind::MacCall(mac_placeholder()) }))
dfeec247 89 }
b7449926 90 AstFragmentKind::Stmts => AstFragment::Stmts(smallvec![{
dfeec247 91 let mac = P((mac_placeholder(), ast::MacStmtStyle::Braces, ast::AttrVec::new()));
ba9703b0 92 ast::Stmt { id, span, kind: ast::StmtKind::MacCall(mac) }
b7449926 93 }]),
dfeec247
XL
94 AstFragmentKind::Arms => AstFragment::Arms(smallvec![ast::Arm {
95 attrs: Default::default(),
96 body: expr_placeholder(),
97 guard: None,
98 id,
99 pat: pat(),
100 span,
101 is_placeholder: true,
102 }]),
103 AstFragmentKind::Fields => AstFragment::Fields(smallvec![ast::Field {
104 attrs: Default::default(),
105 expr: expr_placeholder(),
106 id,
107 ident,
108 is_shorthand: false,
109 span,
110 is_placeholder: true,
111 }]),
112 AstFragmentKind::FieldPats => AstFragment::FieldPats(smallvec![ast::FieldPat {
113 attrs: Default::default(),
114 id,
115 ident,
116 is_shorthand: false,
117 pat: pat(),
118 span,
119 is_placeholder: true,
120 }]),
e1599b0c
XL
121 AstFragmentKind::GenericParams => AstFragment::GenericParams(smallvec![{
122 ast::GenericParam {
123 attrs: Default::default(),
124 bounds: Default::default(),
125 id,
126 ident,
127 is_placeholder: true,
128 kind: ast::GenericParamKind::Lifetime,
129 }
130 }]),
dfeec247
XL
131 AstFragmentKind::Params => AstFragment::Params(smallvec![ast::Param {
132 attrs: Default::default(),
133 id,
134 pat: pat(),
135 span,
136 ty: ty(),
137 is_placeholder: true,
138 }]),
139 AstFragmentKind::StructFields => AstFragment::StructFields(smallvec![ast::StructField {
140 attrs: Default::default(),
141 id,
142 ident: None,
143 span,
144 ty: ty(),
145 vis,
146 is_placeholder: true,
147 }]),
148 AstFragmentKind::Variants => AstFragment::Variants(smallvec![ast::Variant {
149 attrs: Default::default(),
150 data: ast::VariantData::Struct(Default::default(), false),
151 disr_expr: None,
152 id,
153 ident,
154 span,
155 vis,
156 is_placeholder: true,
157 }]),
9e0c209e
SL
158 }
159}
160
dc9dc135 161pub struct PlaceholderExpander<'a, 'b> {
b7449926 162 expanded_fragments: FxHashMap<ast::NodeId, AstFragment>,
9e0c209e
SL
163 cx: &'a mut ExtCtxt<'b>,
164 monotonic: bool,
165}
166
167impl<'a, 'b> PlaceholderExpander<'a, 'b> {
168 pub fn new(cx: &'a mut ExtCtxt<'b>, monotonic: bool) -> Self {
dfeec247 169 PlaceholderExpander { cx, expanded_fragments: FxHashMap::default(), monotonic }
9e0c209e
SL
170 }
171
e74abb32 172 pub fn add(&mut self, id: ast::NodeId, mut fragment: AstFragment) {
9fa01778 173 fragment.mut_visit_with(self);
8faf50e0 174 self.expanded_fragments.insert(id, fragment);
9e0c209e
SL
175 }
176
8faf50e0
XL
177 fn remove(&mut self, id: ast::NodeId) -> AstFragment {
178 self.expanded_fragments.remove(&id).unwrap()
9e0c209e
SL
179 }
180}
181
9fa01778 182impl<'a, 'b> MutVisitor for PlaceholderExpander<'a, 'b> {
e1599b0c
XL
183 fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
184 if arm.is_placeholder {
185 self.remove(arm.id).make_arms()
186 } else {
187 noop_flat_map_arm(arm, self)
188 }
189 }
190
191 fn flat_map_field(&mut self, field: ast::Field) -> SmallVec<[ast::Field; 1]> {
192 if field.is_placeholder {
193 self.remove(field.id).make_fields()
194 } else {
195 noop_flat_map_field(field, self)
196 }
197 }
198
199 fn flat_map_field_pattern(&mut self, fp: ast::FieldPat) -> SmallVec<[ast::FieldPat; 1]> {
200 if fp.is_placeholder {
201 self.remove(fp.id).make_field_patterns()
202 } else {
203 noop_flat_map_field_pattern(fp, self)
204 }
205 }
206
207 fn flat_map_generic_param(
208 &mut self,
dfeec247
XL
209 param: ast::GenericParam,
210 ) -> SmallVec<[ast::GenericParam; 1]> {
e1599b0c
XL
211 if param.is_placeholder {
212 self.remove(param.id).make_generic_params()
213 } else {
214 noop_flat_map_generic_param(param, self)
215 }
216 }
217
218 fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
219 if p.is_placeholder {
220 self.remove(p.id).make_params()
221 } else {
222 noop_flat_map_param(p, self)
223 }
224 }
225
226 fn flat_map_struct_field(&mut self, sf: ast::StructField) -> SmallVec<[ast::StructField; 1]> {
227 if sf.is_placeholder {
228 self.remove(sf.id).make_struct_fields()
229 } else {
230 noop_flat_map_struct_field(sf, self)
231 }
232 }
233
234 fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
235 if variant.is_placeholder {
236 self.remove(variant.id).make_variants()
237 } else {
238 noop_flat_map_variant(variant, self)
239 }
240 }
241
9fa01778 242 fn flat_map_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
e74abb32 243 match item.kind {
ba9703b0 244 ast::ItemKind::MacCall(_) => return self.remove(item.id).make_items(),
b7449926 245 ast::ItemKind::MacroDef(_) => return smallvec![item],
32a655c1 246 _ => {}
9e0c209e 247 }
32a655c1 248
9fa01778 249 noop_flat_map_item(item, self)
9e0c209e
SL
250 }
251
74b04a01 252 fn flat_map_trait_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
e74abb32 253 match item.kind {
ba9703b0 254 ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_trait_items(),
dfeec247 255 _ => noop_flat_map_assoc_item(item, self),
9e0c209e
SL
256 }
257 }
258
74b04a01 259 fn flat_map_impl_item(&mut self, item: P<ast::AssocItem>) -> SmallVec<[P<ast::AssocItem>; 1]> {
e74abb32 260 match item.kind {
ba9703b0 261 ast::AssocItemKind::MacCall(_) => self.remove(item.id).make_impl_items(),
dfeec247 262 _ => noop_flat_map_assoc_item(item, self),
9e0c209e
SL
263 }
264 }
265
74b04a01
XL
266 fn flat_map_foreign_item(
267 &mut self,
268 item: P<ast::ForeignItem>,
269 ) -> SmallVec<[P<ast::ForeignItem>; 1]> {
e74abb32 270 match item.kind {
ba9703b0 271 ast::ForeignItemKind::MacCall(_) => self.remove(item.id).make_foreign_items(),
9fa01778 272 _ => noop_flat_map_foreign_item(item, self),
83c7162d
XL
273 }
274 }
275
9fa01778 276 fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
e74abb32 277 match expr.kind {
ba9703b0 278 ast::ExprKind::MacCall(_) => *expr = self.remove(expr.id).make_expr(),
9fa01778 279 _ => noop_visit_expr(expr, self),
9e0c209e
SL
280 }
281 }
282
9fa01778 283 fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
e74abb32 284 match expr.kind {
ba9703b0 285 ast::ExprKind::MacCall(_) => self.remove(expr.id).make_opt_expr(),
9fa01778 286 _ => noop_filter_map_expr(expr, self),
9e0c209e
SL
287 }
288 }
289
9fa01778 290 fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> {
e74abb32 291 let (style, mut stmts) = match stmt.kind {
ba9703b0 292 ast::StmtKind::MacCall(mac) => (mac.1, self.remove(stmt.id).make_stmts()),
9fa01778 293 _ => return noop_flat_map_stmt(stmt, self),
9e0c209e
SL
294 };
295
296 if style == ast::MacStmtStyle::Semicolon {
8faf50e0
XL
297 if let Some(stmt) = stmts.pop() {
298 stmts.push(stmt.add_trailing_semicolon());
9e0c209e
SL
299 }
300 }
301
8faf50e0 302 stmts
9e0c209e
SL
303 }
304
9fa01778 305 fn visit_pat(&mut self, pat: &mut P<ast::Pat>) {
e74abb32 306 match pat.kind {
ba9703b0 307 ast::PatKind::MacCall(_) => *pat = self.remove(pat.id).make_pat(),
9fa01778 308 _ => noop_visit_pat(pat, self),
9e0c209e
SL
309 }
310 }
311
9fa01778 312 fn visit_ty(&mut self, ty: &mut P<ast::Ty>) {
e74abb32 313 match ty.kind {
ba9703b0 314 ast::TyKind::MacCall(_) => *ty = self.remove(ty.id).make_ty(),
9fa01778 315 _ => noop_visit_ty(ty, self),
9e0c209e
SL
316 }
317 }
318
9fa01778
XL
319 fn visit_block(&mut self, block: &mut P<ast::Block>) {
320 noop_visit_block(block, self);
9e0c209e 321
9fa01778 322 for stmt in block.stmts.iter_mut() {
dc9dc135
XL
323 if self.monotonic {
324 assert_eq!(stmt.id, ast::DUMMY_NODE_ID);
325 stmt.id = self.cx.resolver.next_node_id();
9fa01778
XL
326 }
327 }
9e0c209e
SL
328 }
329
9fa01778
XL
330 fn visit_mod(&mut self, module: &mut ast::Mod) {
331 noop_visit_mod(module, self);
e74abb32 332 module.items.retain(|item| match item.kind {
ba9703b0 333 ast::ItemKind::MacCall(_) if !self.cx.ecfg.keep_macs => false, // remove macro definitions
9fa01778 334 _ => true,
9e0c209e 335 });
9e0c209e 336 }
9e0c209e 337
ba9703b0 338 fn visit_mac(&mut self, _mac: &mut ast::MacCall) {
9fa01778 339 // Do nothing.
32a655c1 340 }
9e0c209e 341}