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, 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            parens: ast::Parens::No,
199        }
200    }
201
202    pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound {
203        ast::GenericBound::Trait(self.poly_trait_ref(path.span, path, is_const))
204    }
205
206    pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime {
207        ast::Lifetime { id: ast::DUMMY_NODE_ID, ident: ident.with_span_pos(span) }
208    }
209
210    pub fn lifetime_static(&self, span: Span) -> ast::Lifetime {
211        self.lifetime(span, Ident::new(kw::StaticLifetime, span))
212    }
213
214    pub fn stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt {
215        ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) }
216    }
217
218    pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt {
219        self.stmt_let_ty(sp, mutbl, ident, None, ex)
220    }
221
222    pub fn stmt_let_ty(
223        &self,
224        sp: Span,
225        mutbl: bool,
226        ident: Ident,
227        ty: Option<P<ast::Ty>>,
228        ex: P<ast::Expr>,
229    ) -> ast::Stmt {
230        let pat = if mutbl {
231            self.pat_ident_binding_mode(sp, ident, ast::BindingMode::MUT)
232        } else {
233            self.pat_ident(sp, ident)
234        };
235        let local = P(ast::Local {
236            super_: None,
237            pat,
238            ty,
239            id: ast::DUMMY_NODE_ID,
240            kind: LocalKind::Init(ex),
241            span: sp,
242            colon_sp: None,
243            attrs: AttrVec::new(),
244            tokens: None,
245        });
246        self.stmt_local(local, sp)
247    }
248
249    /// Generates `let _: Type;`, which is usually used for type assertions.
250    pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt {
251        let local = P(ast::Local {
252            super_: None,
253            pat: self.pat_wild(span),
254            ty: Some(ty),
255            id: ast::DUMMY_NODE_ID,
256            kind: LocalKind::Decl,
257            span,
258            colon_sp: None,
259            attrs: AttrVec::new(),
260            tokens: None,
261        });
262        self.stmt_local(local, span)
263    }
264
265    pub fn stmt_semi(&self, expr: P<ast::Expr>) -> ast::Stmt {
266        ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Semi(expr) }
267    }
268
269    pub fn stmt_local(&self, local: P<ast::Local>, span: Span) -> ast::Stmt {
270        ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span }
271    }
272
273    pub fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt {
274        ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp }
275    }
276
277    pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> {
278        self.block(
279            expr.span,
280            thin_vec![ast::Stmt {
281                id: ast::DUMMY_NODE_ID,
282                span: expr.span,
283                kind: ast::StmtKind::Expr(expr),
284            }],
285        )
286    }
287    pub fn block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> P<ast::Block> {
288        P(ast::Block {
289            stmts,
290            id: ast::DUMMY_NODE_ID,
291            rules: BlockCheckMode::Default,
292            span,
293            tokens: None,
294        })
295    }
296
297    pub fn expr(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr> {
298        P(ast::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new(), tokens: None })
299    }
300
301    pub fn expr_path(&self, path: ast::Path) -> P<ast::Expr> {
302        self.expr(path.span, ast::ExprKind::Path(None, path))
303    }
304
305    pub fn expr_ident(&self, span: Span, id: Ident) -> P<ast::Expr> {
306        self.expr_path(self.path_ident(span, id))
307    }
308    pub fn expr_self(&self, span: Span) -> P<ast::Expr> {
309        self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
310    }
311
312    pub fn expr_macro_call(&self, span: Span, call: P<ast::MacCall>) -> P<ast::Expr> {
313        self.expr(span, ast::ExprKind::MacCall(call))
314    }
315
316    pub fn expr_binary(
317        &self,
318        sp: Span,
319        op: ast::BinOpKind,
320        lhs: P<ast::Expr>,
321        rhs: P<ast::Expr>,
322    ) -> P<ast::Expr> {
323        self.expr(sp, ast::ExprKind::Binary(Spanned { node: op, span: sp }, lhs, rhs))
324    }
325
326    pub fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
327        self.expr(sp, ast::ExprKind::Unary(UnOp::Deref, e))
328    }
329
330    pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
331        self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e))
332    }
333
334    pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> {
335        self.expr(sp, ast::ExprKind::Paren(e))
336    }
337
338    pub fn expr_method_call(
339        &self,
340        span: Span,
341        expr: P<ast::Expr>,
342        ident: Ident,
343        args: ThinVec<P<ast::Expr>>,
344    ) -> P<ast::Expr> {
345        let seg = ast::PathSegment::from_ident(ident);
346        self.expr(
347            span,
348            ast::ExprKind::MethodCall(Box::new(ast::MethodCall {
349                seg,
350                receiver: expr,
351                args,
352                span,
353            })),
354        )
355    }
356
357    pub fn expr_call(
358        &self,
359        span: Span,
360        expr: P<ast::Expr>,
361        args: ThinVec<P<ast::Expr>>,
362    ) -> P<ast::Expr> {
363        self.expr(span, ast::ExprKind::Call(expr, args))
364    }
365    pub fn expr_loop(&self, sp: Span, block: P<ast::Block>) -> P<ast::Expr> {
366        self.expr(sp, ast::ExprKind::Loop(block, None, sp))
367    }
368    pub fn expr_asm(&self, sp: Span, expr: P<ast::InlineAsm>) -> P<ast::Expr> {
369        self.expr(sp, ast::ExprKind::InlineAsm(expr))
370    }
371    pub fn expr_call_ident(
372        &self,
373        span: Span,
374        id: Ident,
375        args: ThinVec<P<ast::Expr>>,
376    ) -> P<ast::Expr> {
377        self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args))
378    }
379    pub fn expr_call_global(
380        &self,
381        sp: Span,
382        fn_path: Vec<Ident>,
383        args: ThinVec<P<ast::Expr>>,
384    ) -> P<ast::Expr> {
385        let pathexpr = self.expr_path(self.path_global(sp, fn_path));
386        self.expr_call(sp, pathexpr, args)
387    }
388    pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> {
389        self.expr(b.span, ast::ExprKind::Block(b, None))
390    }
391    pub fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::ExprField {
392        ast::ExprField {
393            ident: ident.with_span_pos(span),
394            expr: e,
395            span,
396            is_shorthand: false,
397            attrs: AttrVec::new(),
398            id: ast::DUMMY_NODE_ID,
399            is_placeholder: false,
400        }
401    }
402    pub fn expr_struct(
403        &self,
404        span: Span,
405        path: ast::Path,
406        fields: ThinVec<ast::ExprField>,
407    ) -> P<ast::Expr> {
408        self.expr(
409            span,
410            ast::ExprKind::Struct(P(ast::StructExpr {
411                qself: None,
412                path,
413                fields,
414                rest: ast::StructRest::None,
415            })),
416        )
417    }
418    pub fn expr_struct_ident(
419        &self,
420        span: Span,
421        id: Ident,
422        fields: ThinVec<ast::ExprField>,
423    ) -> P<ast::Expr> {
424        self.expr_struct(span, self.path_ident(span, id), fields)
425    }
426
427    pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> {
428        let suffix = Some(ast::UintTy::Usize.name());
429        let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
430        self.expr(span, ast::ExprKind::Lit(lit))
431    }
432
433    pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> {
434        let suffix = Some(ast::UintTy::U32.name());
435        let lit = token::Lit::new(token::Integer, sym::integer(n), suffix);
436        self.expr(span, ast::ExprKind::Lit(lit))
437    }
438
439    pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> {
440        let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None);
441        self.expr(span, ast::ExprKind::Lit(lit))
442    }
443
444    pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> {
445        let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None);
446        self.expr(span, ast::ExprKind::Lit(lit))
447    }
448
449    pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> {
450        let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None);
451        self.expr(span, ast::ExprKind::Lit(lit))
452    }
453
454    /// `[expr1, expr2, ...]`
455    pub fn expr_array(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
456        self.expr(sp, ast::ExprKind::Array(exprs))
457    }
458
459    /// `&[expr1, expr2, ...]`
460    pub fn expr_array_ref(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
461        self.expr_addr_of(sp, self.expr_array(sp, exprs))
462    }
463
464    pub fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
465        let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
466        self.expr_call_global(sp, some, thin_vec![expr])
467    }
468
469    pub fn expr_none(&self, sp: Span) -> P<ast::Expr> {
470        let none = self.std_path(&[sym::option, sym::Option, sym::None]);
471        self.expr_path(self.path_global(sp, none))
472    }
473    pub fn expr_tuple(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> {
474        self.expr(sp, ast::ExprKind::Tup(exprs))
475    }
476
477    pub fn expr_unreachable(&self, span: Span) -> P<ast::Expr> {
478        self.expr_macro_call(
479            span,
480            self.macro_call(
481                span,
482                self.path_global(
483                    span,
484                    [sym::std, sym::unreachable].map(|s| Ident::new(s, span)).to_vec(),
485                ),
486                Delimiter::Parenthesis,
487                TokenStream::default(),
488            ),
489        )
490    }
491
492    pub fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> {
493        let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
494        self.expr_call_global(sp, ok, thin_vec![expr])
495    }
496
497    pub fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> {
498        let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]);
499        let ok_path = self.path_global(sp, ok);
500        let err = self.std_path(&[sym::result, sym::Result, sym::Err]);
501        let err_path = self.path_global(sp, err);
502
503        let binding_variable = Ident::new(sym::__try_var, sp);
504        let binding_pat = self.pat_ident(sp, binding_variable);
505        let binding_expr = self.expr_ident(sp, binding_variable);
506
507        // `Ok(__try_var)` pattern
508        let ok_pat = self.pat_tuple_struct(sp, ok_path, thin_vec![binding_pat.clone()]);
509
510        // `Err(__try_var)` (pattern and expression respectively)
511        let err_pat = self.pat_tuple_struct(sp, err_path.clone(), thin_vec![binding_pat]);
512        let err_inner_expr =
513            self.expr_call(sp, self.expr_path(err_path), thin_vec![binding_expr.clone()]);
514        // `return Err(__try_var)`
515        let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr)));
516
517        // `Ok(__try_var) => __try_var`
518        let ok_arm = self.arm(sp, ok_pat, binding_expr);
519        // `Err(__try_var) => return Err(__try_var)`
520        let err_arm = self.arm(sp, err_pat, err_expr);
521
522        // `match head { Ok() => ..., Err() => ... }`
523        self.expr_match(sp, head, thin_vec![ok_arm, err_arm])
524    }
525
526    pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
527        P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
528    }
529    pub fn pat_wild(&self, span: Span) -> P<ast::Pat> {
530        self.pat(span, PatKind::Wild)
531    }
532    pub fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat> {
533        self.pat(span, PatKind::Expr(expr))
534    }
535    pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> {
536        self.pat_ident_binding_mode(span, ident, ast::BindingMode::NONE)
537    }
538
539    pub fn pat_ident_binding_mode(
540        &self,
541        span: Span,
542        ident: Ident,
543        ann: ast::BindingMode,
544    ) -> P<ast::Pat> {
545        let pat = PatKind::Ident(ann, ident.with_span_pos(span), None);
546        self.pat(span, pat)
547    }
548    pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> {
549        self.pat(span, PatKind::Path(None, path))
550    }
551    pub fn pat_tuple_struct(
552        &self,
553        span: Span,
554        path: ast::Path,
555        subpats: ThinVec<P<ast::Pat>>,
556    ) -> P<ast::Pat> {
557        self.pat(span, PatKind::TupleStruct(None, path, subpats))
558    }
559    pub fn pat_struct(
560        &self,
561        span: Span,
562        path: ast::Path,
563        field_pats: ThinVec<ast::PatField>,
564    ) -> P<ast::Pat> {
565        self.pat(span, PatKind::Struct(None, path, field_pats, ast::PatFieldsRest::None))
566    }
567    pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> {
568        self.pat(span, PatKind::Tuple(pats))
569    }
570
571    pub fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> {
572        let some = self.std_path(&[sym::option, sym::Option, sym::Some]);
573        let path = self.path_global(span, some);
574        self.pat_tuple_struct(span, path, thin_vec![pat])
575    }
576
577    pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm {
578        ast::Arm {
579            attrs: AttrVec::new(),
580            pat,
581            guard: None,
582            body: Some(expr),
583            span,
584            id: ast::DUMMY_NODE_ID,
585            is_placeholder: false,
586        }
587    }
588
589    pub fn arm_unreachable(&self, span: Span) -> ast::Arm {
590        self.arm(span, self.pat_wild(span), self.expr_unreachable(span))
591    }
592
593    pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> {
594        self.expr(span, ast::ExprKind::Match(arg, arms, MatchKind::Prefix))
595    }
596
597    pub fn expr_if(
598        &self,
599        span: Span,
600        cond: P<ast::Expr>,
601        then: P<ast::Expr>,
602        els: Option<P<ast::Expr>>,
603    ) -> P<ast::Expr> {
604        let els = els.map(|x| self.expr_block(self.block_expr(x)));
605        self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els))
606    }
607
608    pub fn lambda(&self, span: Span, ids: Vec<Ident>, body: P<ast::Expr>) -> P<ast::Expr> {
609        let fn_decl = self.fn_decl(
610            ids.iter().map(|id| self.param(span, *id, self.ty(span, ast::TyKind::Infer))).collect(),
611            ast::FnRetTy::Default(span),
612        );
613
614        // FIXME -- We are using `span` as the span of the `|...|`
615        // part of the lambda, but it probably (maybe?) corresponds to
616        // the entire lambda body. Probably we should extend the API
617        // here, but that's not entirely clear.
618        self.expr(
619            span,
620            ast::ExprKind::Closure(Box::new(ast::Closure {
621                binder: ast::ClosureBinder::NotPresent,
622                capture_clause: ast::CaptureBy::Ref,
623                constness: ast::Const::No,
624                coroutine_kind: None,
625                movability: ast::Movability::Movable,
626                fn_decl,
627                body,
628                fn_decl_span: span,
629                // FIXME(SarthakSingh31): This points to the start of the declaration block and
630                // not the span of the argument block.
631                fn_arg_span: span,
632            })),
633        )
634    }
635
636    pub fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> {
637        self.lambda(span, Vec::new(), body)
638    }
639
640    pub fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: Ident) -> P<ast::Expr> {
641        self.lambda(span, vec![ident], body)
642    }
643
644    pub fn lambda_stmts_1(
645        &self,
646        span: Span,
647        stmts: ThinVec<ast::Stmt>,
648        ident: Ident,
649    ) -> P<ast::Expr> {
650        self.lambda1(span, self.expr_block(self.block(span, stmts)), ident)
651    }
652
653    pub fn param(&self, span: Span, ident: Ident, ty: P<ast::Ty>) -> ast::Param {
654        let arg_pat = self.pat_ident(span, ident);
655        ast::Param {
656            attrs: AttrVec::default(),
657            id: ast::DUMMY_NODE_ID,
658            pat: arg_pat,
659            span,
660            ty,
661            is_placeholder: false,
662        }
663    }
664
665    // `self` is unused but keep it as method for the convenience use.
666    pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> {
667        P(ast::FnDecl { inputs, output })
668    }
669
670    pub fn item(&self, span: Span, attrs: ast::AttrVec, kind: ast::ItemKind) -> P<ast::Item> {
671        P(ast::Item {
672            attrs,
673            id: ast::DUMMY_NODE_ID,
674            kind,
675            vis: ast::Visibility {
676                span: span.shrink_to_lo(),
677                kind: ast::VisibilityKind::Inherited,
678                tokens: None,
679            },
680            span,
681            tokens: None,
682        })
683    }
684
685    pub fn item_static(
686        &self,
687        span: Span,
688        ident: Ident,
689        ty: P<ast::Ty>,
690        mutability: ast::Mutability,
691        expr: P<ast::Expr>,
692    ) -> P<ast::Item> {
693        self.item(
694            span,
695            AttrVec::new(),
696            ast::ItemKind::Static(
697                ast::StaticItem {
698                    ident,
699                    ty,
700                    safety: ast::Safety::Default,
701                    mutability,
702                    expr: Some(expr),
703                    define_opaque: None,
704                }
705                .into(),
706            ),
707        )
708    }
709
710    pub fn item_const(
711        &self,
712        span: Span,
713        ident: Ident,
714        ty: P<ast::Ty>,
715        expr: P<ast::Expr>,
716    ) -> P<ast::Item> {
717        let defaultness = ast::Defaultness::Final;
718        self.item(
719            span,
720            AttrVec::new(),
721            ast::ItemKind::Const(
722                ast::ConstItem {
723                    defaultness,
724                    ident,
725                    // FIXME(generic_const_items): Pass the generics as a parameter.
726                    generics: ast::Generics::default(),
727                    ty,
728                    expr: Some(expr),
729                    define_opaque: None,
730                }
731                .into(),
732            ),
733        )
734    }
735
736    // Builds `#[name]`.
737    pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute {
738        let g = &self.sess.psess.attr_id_generator;
739        attr::mk_attr_word(g, ast::AttrStyle::Outer, ast::Safety::Default, name, span)
740    }
741
742    // Builds `#[name = val]`.
743    //
744    // Note: `span` is used for both the identifier and the value.
745    pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute {
746        let g = &self.sess.psess.attr_id_generator;
747        attr::mk_attr_name_value_str(
748            g,
749            ast::AttrStyle::Outer,
750            ast::Safety::Default,
751            name,
752            val,
753            span,
754        )
755    }
756
757    // Builds `#[outer(inner)]`.
758    pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute {
759        let g = &self.sess.psess.attr_id_generator;
760        attr::mk_attr_nested_word(
761            g,
762            ast::AttrStyle::Outer,
763            ast::Safety::Default,
764            outer,
765            inner,
766            span,
767        )
768    }
769}