Skip to main content

rustc_expand/
build.rs

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