rustc_expand/
build.rs

1use rustc_ast::ptr::P;
2use rustc_ast::token::Delimiter;
3use rustc_ast::tokenstream::TokenStream;
4use rustc_ast::util::literal;
5use rustc_ast::{
6    self as ast, AnonConst, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp,
7    attr, token, tokenstream,
8};
9use rustc_span::source_map::Spanned;
10use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
11use thin_vec::{ThinVec, thin_vec};
12
13use crate::base::ExtCtxt;
14
15impl<'a> ExtCtxt<'a> {
16    pub fn path(&self, span: Span, strs: Vec<Ident>) -> ast::Path {
17        self.path_all(span, false, strs, vec![])
18    }
19    pub fn path_ident(&self, span: Span, id: Ident) -> ast::Path {
20        self.path(span, vec![id])
21    }
22    pub fn path_global(&self, span: Span, strs: Vec<Ident>) -> ast::Path {
23        self.path_all(span, true, strs, vec![])
24    }
25    pub fn path_all(
26        &self,
27        span: Span,
28        global: bool,
29        mut idents: Vec<Ident>,
30        args: Vec<ast::GenericArg>,
31    ) -> ast::Path {
32        assert!(!idents.is_empty());
33        let add_root = global && !idents[0].is_path_segment_keyword();
34        let mut segments = ThinVec::with_capacity(idents.len() + add_root as usize);
35        if add_root {
36            segments.push(ast::PathSegment::path_root(span));
37        }
38        let last_ident = idents.pop().unwrap();
39        segments.extend(
40            idents.into_iter().map(|ident| ast::PathSegment::from_ident(ident.with_span_pos(span))),
41        );
42        let args = if !args.is_empty() {
43            let args = args.into_iter().map(ast::AngleBracketedArg::Arg).collect();
44            Some(ast::AngleBracketedArgs { args, span }.into())
45        } else {
46            None
47        };
48        segments.push(ast::PathSegment {
49            ident: last_ident.with_span_pos(span),
50            id: ast::DUMMY_NODE_ID,
51            args,
52        });
53        ast::Path { span, segments, tokens: None }
54    }
55
56    pub fn macro_call(
57        &self,
58        span: Span,
59        path: ast::Path,
60        delim: Delimiter,
61        tokens: TokenStream,
62    ) -> P<ast::MacCall> {
63        P(ast::MacCall {
64            path,
65            args: P(ast::DelimArgs {
66                dspan: tokenstream::DelimSpan { open: span, close: span },
67                delim,
68                tokens,
69            }),
70        })
71    }
72
73    pub fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
74        ast::MutTy { ty, mutbl }
75    }
76
77    pub fn ty(&self, span: Span, kind: ast::TyKind) -> P<ast::Ty> {
78        P(ast::Ty { id: ast::DUMMY_NODE_ID, span, kind, tokens: None })
79    }
80
81    pub fn ty_infer(&self, span: Span) -> P<ast::Ty> {
82        self.ty(span, ast::TyKind::Infer)
83    }
84
85    pub fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
86        self.ty(path.span, ast::TyKind::Path(None, path))
87    }
88
89    // Might need to take bounds as an argument in the future, if you ever want
90    // to generate a bounded existential trait type.
91    pub fn ty_ident(&self, span: Span, ident: Ident) -> P<ast::Ty> {
92        self.ty_path(self.path_ident(span, ident))
93    }
94
95    pub fn anon_const(&self, span: Span, kind: ast::ExprKind) -> ast::AnonConst {
96        ast::AnonConst {
97            id: ast::DUMMY_NODE_ID,
98            value: P(ast::Expr {
99                id: ast::DUMMY_NODE_ID,
100                kind,
101                span,
102                attrs: AttrVec::new(),
103                tokens: None,
104            }),
105        }
106    }
107
108    pub fn const_ident(&self, span: Span, ident: Ident) -> ast::AnonConst {
109        self.anon_const(span, ast::ExprKind::Path(None, self.path_ident(span, ident)))
110    }
111
112    pub fn ty_ref(
113        &self,
114        span: Span,
115        ty: P<ast::Ty>,
116        lifetime: Option<ast::Lifetime>,
117        mutbl: ast::Mutability,
118    ) -> P<ast::Ty> {
119        self.ty(span, ast::TyKind::Ref(lifetime, self.ty_mt(ty, mutbl)))
120    }
121
122    pub fn ty_ptr(&self, span: Span, ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty> {
123        self.ty(span, ast::TyKind::Ptr(self.ty_mt(ty, mutbl)))
124    }
125
126    pub fn typaram(
127        &self,
128        span: Span,
129        ident: Ident,
130        bounds: ast::GenericBounds,
131        default: Option<P<ast::Ty>>,
132    ) -> ast::GenericParam {
133        ast::GenericParam {
134            ident: ident.with_span_pos(span),
135            id: ast::DUMMY_NODE_ID,
136            attrs: AttrVec::new(),
137            bounds,
138            kind: ast::GenericParamKind::Type { default },
139            is_placeholder: false,
140            colon_span: None,
141        }
142    }
143
144    pub fn lifetime_param(
145        &self,
146        span: Span,
147        ident: Ident,
148        bounds: ast::GenericBounds,
149    ) -> ast::GenericParam {
150        ast::GenericParam {
151            id: ast::DUMMY_NODE_ID,
152            ident: ident.with_span_pos(span),
153            attrs: AttrVec::new(),
154            bounds,
155            is_placeholder: false,
156            kind: ast::GenericParamKind::Lifetime,
157            colon_span: None,
158        }
159    }
160
161    pub fn const_param(
162        &self,
163        span: Span,
164        ident: Ident,
165        bounds: ast::GenericBounds,
166        ty: P<ast::Ty>,
167        default: Option<AnonConst>,
168    ) -> ast::GenericParam {
169        ast::GenericParam {
170            id: ast::DUMMY_NODE_ID,
171            ident: ident.with_span_pos(span),
172            attrs: AttrVec::new(),
173            bounds,
174            is_placeholder: false,
175            kind: ast::GenericParamKind::Const { ty, kw_span: DUMMY_SP, default },
176            colon_span: None,
177        }
178    }
179
180    pub fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
181        ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID }
182    }
183
184    pub fn poly_trait_ref(&self, span: Span, path: ast::Path, is_const: bool) -> ast::PolyTraitRef {
185        ast::PolyTraitRef {
186            bound_generic_params: ThinVec::new(),
187            modifiers: ast::TraitBoundModifiers {
188                polarity: ast::BoundPolarity::Positive,
189                constness: if is_const {
190                    ast::BoundConstness::Maybe(DUMMY_SP)
191                } else {
192                    ast::BoundConstness::Never
193                },
194                asyncness: ast::BoundAsyncness::Normal,
195            },
196            trait_ref: self.trait_ref(path),
197            span,
198        }
199    }
200
201    pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
202        ast::GenericBound::Trait(self.poly_trait_ref(path.span, path, is_const))
203    }
204
205    pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime {
206        ast::Lifetime { id: ast::DUMMY_NODE_ID, ident: ident.with_span_pos(span) }
207    }
208
209    pub fn lifetime_static(&self, span: Span) -> ast::Lifetime {
210        self.lifetime(span, Ident::new(kw::StaticLifetime, span))
211    }
212
213    pub fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt {
214        ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) }
215    }
216
217    pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt {
218        self.stmt_let_ty(sp, mutbl, ident, None, ex)
219    }
220
221    pub fn stmt_let_ty(
222        &self,
223        sp: Span,
224        mutbl: bool,
225        ident: Ident,
226        ty: Option<P<ast::Ty>>,
227        ex: P<ast::Expr>,
228    ) -> ast::Stmt {
229        let pat = if mutbl {
230            self.pat_ident_binding_mode(sp, ident, ast::BindingMode::MUT)
231        } else {
232            self.pat_ident(sp, ident)
233        };
234        let local = P(ast::Local {
235            super_: None,
236            pat,
237            ty,
238            id: ast::DUMMY_NODE_ID,
239            kind: LocalKind::Init(ex),
240            span: sp,
241            colon_sp: None,
242            attrs: AttrVec::new(),
243            tokens: None,
244        });
245        self.stmt_local(local, sp)
246    }
247
248    /// Generates `let _: Type;`, which is usually used for type assertions.
249    pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
250        let local = P(ast::Local {
251            super_: None,
252            pat: self.pat_wild(span),
253            ty: Some(ty),
254            id: ast::DUMMY_NODE_ID,
255            kind: LocalKind::Decl,
256            span,
257            colon_sp: None,
258            attrs: AttrVec::new(),
259            tokens: None,
260        });
261        self.stmt_local(local, span)
262    }
263
264    pub fn stmt_semi(&self, expr: P<ast::Expr>) -> ast::Stmt {
265        ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Semi(expr) }
266    }
267
268    pub fn stmt_local(&self, local: P<ast::Local>, span: Span) -> ast::Stmt {
269        ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span }
270    }
271
272    pub fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt {
273        ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp }
274    }
275
276    pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
277        self.block(
278            expr.span,
279            thin_vec![ast::Stmt {
280                id: ast::DUMMY_NODE_ID,
281                span: expr.span,
282                kind: ast::StmtKind::Expr(expr),
283            }],
284        )
285    }
286    pub fn block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> P<ast::Block> {
287        P(ast::Block {
288            stmts,
289            id: ast::DUMMY_NODE_ID,
290            rules: BlockCheckMode::Default,
291            span,
292            tokens: None,
293        })
294    }
295
296    pub fn expr(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr> {
297        P(ast::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new(), tokens: None })
298    }
299
300    pub fn expr_path(&self, path: ast::Path) -> P<ast::Expr> {
301        self.expr(path.span, ast::ExprKind::Path(None, path))
302    }
303
304    pub fn expr_ident(&self, span: Span, id: Ident) -> P<ast::Expr> {
305        self.expr_path(self.path_ident(span, id))
306    }
307    pub fn expr_self(&self, span: Span) -> P<ast::Expr> {
308        self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
309    }
310
311    pub fn expr_macro_call(&self, span: Span, call: P<ast::MacCall>) -> P<ast::Expr> {
312        self.expr(span, ast::ExprKind::MacCall(call))
313    }
314
315    pub fn expr_binary(
316        &self,
317        sp: Span,
318        op: ast::BinOpKind,
319        lhs: P<ast::Expr>,
320        rhs: P<ast::Expr>,
321    ) -> P<ast::Expr> {
322        self.expr(sp, ast::ExprKind::Binary(Spanned { node: op, span: sp }, lhs, rhs))
323    }
324
325    pub fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
326        self.expr(sp, ast::ExprKind::Unary(UnOp::Deref, e))
327    }
328
329    pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
330        self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
331    }
332
333    pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
334        self.expr(sp, ast::ExprKind::Paren(e))
335    }
336
337    pub fn expr_method_call(
338        &self,
339        span: Span,
340        expr: P<ast::Expr>,
341        ident: Ident,
342        args: ThinVec<P<ast::Expr>>,
343    ) -> P<ast::Expr> {
344        let seg = ast::PathSegment::from_ident(ident);
345        self.expr(
346            span,
347            ast::ExprKind::MethodCall(Box::new(ast::MethodCall {
348                seg,
349                receiver: expr,
350                args,
351                span,
352            })),
353        )
354    }
355
356    pub fn expr_call(
357        &self,
358        span: Span,
359        expr: P<ast::Expr>,
360        args: ThinVec<P<ast::Expr>>,
361    ) -> P<ast::Expr> {
362        self.expr(span, ast::ExprKind::Call(expr, args))
363    }
364    pub fn expr_loop(&self, sp: Span, block: P<ast::Block>) -> P<ast::Expr> {
365        self.expr(sp, ast::ExprKind::Loop(block, None, sp))
366    }
367    pub fn expr_asm(&self, sp: Span, expr: P<ast::InlineAsm>) -> P<ast::Expr> {
368        self.expr(sp, ast::ExprKind::InlineAsm(expr))
369    }
370    pub fn expr_call_ident(
371        &self,
372        span: Span,
373        id: Ident,
374        args: ThinVec<P<ast::Expr>>,
375    ) -> P<ast::Expr> {
376        self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args))
377    }
378    pub fn expr_call_global(
379        &self,
380        sp: Span,
381        fn_path: Vec<Ident>,
382        args: ThinVec<P<ast::Expr>>,
383    ) -> P<ast::Expr> {
384        let pathexpr = self.expr_path(self.path_global(sp, fn_path));
385        self.expr_call(sp, pathexpr, args)
386    }
387    pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
388        self.expr(b.span, ast::ExprKind::Block(b, None))
389    }
390    pub fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::ExprField {
391        ast::ExprField {
392            ident: ident.with_span_pos(span),
393            expr: e,
394            span,
395            is_shorthand: false,
396            attrs: AttrVec::new(),
397            id: ast::DUMMY_NODE_ID,
398            is_placeholder: false,
399        }
400    }
401    pub fn expr_struct(
402        &self,
403        span: Span,
404        path: ast::Path,
405        fields: ThinVec<ast::ExprField>,
406    ) -> P<ast::Expr> {
407        self.expr(
408            span,
409            ast::ExprKind::Struct(P(ast::StructExpr {
410                qself: None,
411                path,
412                fields,
413                rest: ast::StructRest::None,
414            })),
415        )
416    }
417    pub fn expr_struct_ident(
418        &self,
419        span: Span,
420        id: Ident,
421        fields: ThinVec<ast::ExprField>,
422    ) -> P<ast::Expr> {
423        self.expr_struct(span, self.path_ident(span, id), fields)
424    }
425
426    pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> {
427        let suffix = Some(ast::UintTy::Usize.name());
428        let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
429        self.expr(span, ast::ExprKind::Lit(lit))
430    }
431
432    pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> {
433        let suffix = Some(ast::UintTy::U32.name());
434        let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
435        self.expr(span, ast::ExprKind::Lit(lit))
436    }
437
438    pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> {
439        let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None);
440        self.expr(span, ast::ExprKind::Lit(lit))
441    }
442
443    pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> {
444        let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None);
445        self.expr(span, ast::ExprKind::Lit(lit))
446    }
447
448    pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> {
449        let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None);
450        self.expr(span, ast::ExprKind::Lit(lit))
451    }
452
453    /// `[expr1, expr2, ...]`
454    pub fn expr_array(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
455        self.expr(sp, ast::ExprKind::Array(exprs))
456    }
457
458    /// `&[expr1, expr2, ...]`
459    pub fn expr_array_ref(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
460        self.expr_addr_of(sp, self.expr_array(sp, exprs))
461    }
462
463    pub fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
464        let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
465        self.expr_call_global(sp, some, thin_vec![expr])
466    }
467
468    pub fn expr_none(&self, sp: Span) -> P<ast::Expr> {
469        let none = self.std_path(&[sym::option, sym::Option, sym::None]);
470        self.expr_path(self.path_global(sp, none))
471    }
472    pub fn expr_tuple(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
473        self.expr(sp, ast::ExprKind::Tup(exprs))
474    }
475
476    pub fn expr_unreachable(&self, span: Span) -> P<ast::Expr> {
477        self.expr_macro_call(
478            span,
479            self.macro_call(
480                span,
481                self.path_global(
482                    span,
483                    [sym::std, sym::unreachable].map(|s| Ident::new(s, span)).to_vec(),
484                ),
485                Delimiter::Parenthesis,
486                TokenStream::default(),
487            ),
488        )
489    }
490
491    pub fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
492        let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
493        self.expr_call_global(sp, ok, thin_vec![expr])
494    }
495
496    pub fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> {
497        let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
498        let ok_path = self.path_global(sp, ok);
499        let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
500        let err_path = self.path_global(sp, err);
501
502        let binding_variable = Ident::new(sym::__try_var, sp);
503        let binding_pat = self.pat_ident(sp, binding_variable);
504        let binding_expr = self.expr_ident(sp, binding_variable);
505
506        // `Ok(__try_var)` pattern
507        let ok_pat = self.pat_tuple_struct(sp, ok_path, thin_vec![binding_pat.clone()]);
508
509        // `Err(__try_var)` (pattern and expression respectively)
510        let err_pat = self.pat_tuple_struct(sp, err_path.clone(), thin_vec![binding_pat]);
511        let err_inner_expr =
512            self.expr_call(sp, self.expr_path(err_path), thin_vec![binding_expr.clone()]);
513        // `return Err(__try_var)`
514        let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr)));
515
516        // `Ok(__try_var) => __try_var`
517        let ok_arm = self.arm(sp, ok_pat, binding_expr);
518        // `Err(__try_var) => return Err(__try_var)`
519        let err_arm = self.arm(sp, err_pat, err_expr);
520
521        // `match head { Ok() => ..., Err() => ... }`
522        self.expr_match(sp, head, thin_vec![ok_arm, err_arm])
523    }
524
525    pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
526        P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
527    }
528    pub fn pat_wild(&self, span: Span) -> P<ast::Pat> {
529        self.pat(span, PatKind::Wild)
530    }
531    pub fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat> {
532        self.pat(span, PatKind::Expr(expr))
533    }
534    pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> {
535        self.pat_ident_binding_mode(span, ident, ast::BindingMode::NONE)
536    }
537
538    pub fn pat_ident_binding_mode(
539        &self,
540        span: Span,
541        ident: Ident,
542        ann: ast::BindingMode,
543    ) -> P<ast::Pat> {
544        let pat = PatKind::Ident(ann, ident.with_span_pos(span), None);
545        self.pat(span, pat)
546    }
547    pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
548        self.pat(span, PatKind::Path(None, path))
549    }
550    pub fn pat_tuple_struct(
551        &self,
552        span: Span,
553        path: ast::Path,
554        subpats: ThinVec<P<ast::Pat>>,
555    ) -> P<ast::Pat> {
556        self.pat(span, PatKind::TupleStruct(None, path, subpats))
557    }
558    pub fn pat_struct(
559        &self,
560        span: Span,
561        path: ast::Path,
562        field_pats: ThinVec<ast::PatField>,
563    ) -> P<ast::Pat> {
564        self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None))
565    }
566    pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
567        self.pat(span, PatKind::Tuple(pats))
568    }
569
570    pub fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
571        let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
572        let path = self.path_global(span, some);
573        self.pat_tuple_struct(span, path, thin_vec![pat])
574    }
575
576    pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
577        ast::Arm {
578            attrs: AttrVec::new(),
579            pat,
580            guard: None,
581            body: Some(expr),
582            span,
583            id: ast::DUMMY_NODE_ID,
584            is_placeholder: false,
585        }
586    }
587
588    pub fn arm_unreachable(&self, span: Span) -> ast::Arm {
589        self.arm(span, self.pat_wild(span), self.expr_unreachable(span))
590    }
591
592    pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
593        self.expr(span, ast::ExprKind::Match(arg, arms, MatchKind::Prefix))
594    }
595
596    pub fn expr_if(
597        &self,
598        span: Span,
599        cond: P<ast::Expr>,
600        then: P<ast::Expr>,
601        els: Option<P<ast::Expr>>,
602    ) -> P<ast::Expr> {
603        let els = els.map(|x| self.expr_block(self.block_expr(x)));
604        self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els))
605    }
606
607    pub fn lambda(&self, span: Span, ids: Vec<Ident>, body: P<ast::Expr>) -> P<ast::Expr> {
608        let fn_decl = self.fn_decl(
609            ids.iter().map(|id| self.param(span, *id, self.ty(span, ast::TyKind::Infer))).collect(),
610            ast::FnRetTy::Default(span),
611        );
612
613        // FIXME -- We are using `span` as the span of the `|...|`
614        // part of the lambda, but it probably (maybe?) corresponds to
615        // the entire lambda body. Probably we should extend the API
616        // here, but that's not entirely clear.
617        self.expr(
618            span,
619            ast::ExprKind::Closure(Box::new(ast::Closure {
620                binder: ast::ClosureBinder::NotPresent,
621                capture_clause: ast::CaptureBy::Ref,
622                constness: ast::Const::No,
623                coroutine_kind: None,
624                movability: ast::Movability::Movable,
625                fn_decl,
626                body,
627                fn_decl_span: span,
628                // FIXME(SarthakSingh31): This points to the start of the declaration block and
629                // not the span of the argument block.
630                fn_arg_span: span,
631            })),
632        )
633    }
634
635    pub fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> {
636        self.lambda(span, Vec::new(), body)
637    }
638
639    pub fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: Ident) -> P<ast::Expr> {
640        self.lambda(span, vec![ident], body)
641    }
642
643    pub fn lambda_stmts_1(
644        &self,
645        span: Span,
646        stmts: ThinVec<ast::Stmt>,
647        ident: Ident,
648    ) -> P<ast::Expr> {
649        self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
650    }
651
652    pub fn param(&self, span: Span, ident: Ident, ty: P<ast::Ty>) -> ast::Param {
653        let arg_pat = self.pat_ident(span, ident);
654        ast::Param {
655            attrs: AttrVec::default(),
656            id: ast::DUMMY_NODE_ID,
657            pat: arg_pat,
658            span,
659            ty,
660            is_placeholder: false,
661        }
662    }
663
664    // `self` is unused but keep it as method for the convenience use.
665    pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
666        P(ast::FnDecl { inputs, output })
667    }
668
669    pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> P<ast::Item> {
670        P(ast::Item {
671            attrs,
672            id: ast::DUMMY_NODE_ID,
673            kind,
674            vis: ast::Visibility {
675                span: span.shrink_to_lo(),
676                kind: ast::VisibilityKind::Inherited,
677                tokens: None,
678            },
679            span,
680            tokens: None,
681        })
682    }
683
684    pub fn item_static(
685        &self,
686        span: Span,
687        ident: Ident,
688        ty: P<ast::Ty>,
689        mutability: ast::Mutability,
690        expr: P<ast::Expr>,
691    ) -> P<ast::Item> {
692        self.item(
693            span,
694            AttrVec::new(),
695            ast::ItemKind::Static(
696                ast::StaticItem {
697                    ident,
698                    ty,
699                    safety: ast::Safety::Default,
700                    mutability,
701                    expr: Some(expr),
702                    define_opaque: None,
703                }
704                .into(),
705            ),
706        )
707    }
708
709    pub fn item_const(
710        &self,
711        span: Span,
712        ident: Ident,
713        ty: P<ast::Ty>,
714        expr: P<ast::Expr>,
715    ) -> P<ast::Item> {
716        let defaultness = ast::Defaultness::Final;
717        self.item(
718            span,
719            AttrVec::new(),
720            ast::ItemKind::Const(
721                ast::ConstItem {
722                    defaultness,
723                    ident,
724                    // FIXME(generic_const_items): Pass the generics as a parameter.
725                    generics: ast::Generics::default(),
726                    ty,
727                    expr: Some(expr),
728                    define_opaque: None,
729                }
730                .into(),
731            ),
732        )
733    }
734
735    // Builds `#[name]`.
736    pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
737        let g = &self.sess.psess.attr_id_generator;
738        attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Safety::Default, name, span)
739    }
740
741    // Builds `#[name = val]`.
742    //
743    // Note: `span` is used for both the identifier and the value.
744    pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
745        let g = &self.sess.psess.attr_id_generator;
746        attr::mk_attr_name_value_str(
747            g,
748            ast::AttrStyle::Outer,
749            ast::Safety::Default,
750            name,
751            val,
752            span,
753        )
754    }
755
756    // Builds `#[outer(inner)]`.
757    pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
758        let g = &self.sess.psess.attr_id_generator;
759        attr::mk_attr_nested_word(
760            g,
761            ast::AttrStyle::Outer,
762            ast::Safety::Default,
763            outer,
764            inner,
765            span,
766        )
767    }
768}