Skip to main content

rustc_expand/
build.rs

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