1 use crate::base
::ExtCtxt
;
5 use rustc_ast
::{self as ast, AttrVec, BlockCheckMode, Expr, PatKind, UnOp}
;
6 use rustc_span
::source_map
::Spanned
;
7 use rustc_span
::symbol
::{kw, sym, Ident, Symbol}
;
11 impl<'a
> ExtCtxt
<'a
> {
12 pub fn path(&self, span
: Span
, strs
: Vec
<Ident
>) -> ast
::Path
{
13 self.path_all(span
, false, strs
, vec
![])
15 pub fn path_ident(&self, span
: Span
, id
: Ident
) -> ast
::Path
{
16 self.path(span
, vec
![id
])
18 pub fn path_global(&self, span
: Span
, strs
: Vec
<Ident
>) -> ast
::Path
{
19 self.path_all(span
, true, strs
, vec
![])
25 mut idents
: Vec
<Ident
>,
26 args
: Vec
<ast
::GenericArg
>,
28 assert
!(!idents
.is_empty());
29 let add_root
= global
&& !idents
[0].is_path_segment_keyword();
30 let mut segments
= Vec
::with_capacity(idents
.len() + add_root
as usize);
32 segments
.push(ast
::PathSegment
::path_root(span
));
34 let last_ident
= idents
.pop().unwrap();
36 idents
.into_iter().map(|ident
| ast
::PathSegment
::from_ident(ident
.with_span_pos(span
))),
38 let args
= if !args
.is_empty() {
39 let args
= args
.into_iter().map(ast
::AngleBracketedArg
::Arg
).collect();
40 ast
::AngleBracketedArgs { args, span }
.into()
44 segments
.push(ast
::PathSegment
{
45 ident
: last_ident
.with_span_pos(span
),
46 id
: ast
::DUMMY_NODE_ID
,
49 ast
::Path { span, segments, tokens: None }
52 pub fn ty_mt(&self, ty
: P
<ast
::Ty
>, mutbl
: ast
::Mutability
) -> ast
::MutTy
{
53 ast
::MutTy { ty, mutbl }
56 pub fn ty(&self, span
: Span
, kind
: ast
::TyKind
) -> P
<ast
::Ty
> {
57 P(ast
::Ty { id: ast::DUMMY_NODE_ID, span, kind, tokens: None }
)
60 pub fn ty_path(&self, path
: ast
::Path
) -> P
<ast
::Ty
> {
61 self.ty(path
.span
, ast
::TyKind
::Path(None
, path
))
64 // Might need to take bounds as an argument in the future, if you ever want
65 // to generate a bounded existential trait type.
66 pub fn ty_ident(&self, span
: Span
, ident
: Ident
) -> P
<ast
::Ty
> {
67 self.ty_path(self.path_ident(span
, ident
))
70 pub fn anon_const(&self, span
: Span
, kind
: ast
::ExprKind
) -> ast
::AnonConst
{
72 id
: ast
::DUMMY_NODE_ID
,
74 id
: ast
::DUMMY_NODE_ID
,
77 attrs
: AttrVec
::new(),
83 pub fn const_ident(&self, span
: Span
, ident
: Ident
) -> ast
::AnonConst
{
84 self.anon_const(span
, ast
::ExprKind
::Path(None
, self.path_ident(span
, ident
)))
91 lifetime
: Option
<ast
::Lifetime
>,
92 mutbl
: ast
::Mutability
,
94 self.ty(span
, ast
::TyKind
::Rptr(lifetime
, self.ty_mt(ty
, mutbl
)))
97 pub fn ty_ptr(&self, span
: Span
, ty
: P
<ast
::Ty
>, mutbl
: ast
::Mutability
) -> P
<ast
::Ty
> {
98 self.ty(span
, ast
::TyKind
::Ptr(self.ty_mt(ty
, mutbl
)))
105 attrs
: Vec
<ast
::Attribute
>,
106 bounds
: ast
::GenericBounds
,
107 default: Option
<P
<ast
::Ty
>>,
108 ) -> ast
::GenericParam
{
110 ident
: ident
.with_span_pos(span
),
111 id
: ast
::DUMMY_NODE_ID
,
114 kind
: ast
::GenericParamKind
::Type { default }
,
115 is_placeholder
: false,
119 pub fn trait_ref(&self, path
: ast
::Path
) -> ast
::TraitRef
{
120 ast
::TraitRef { path, ref_id: ast::DUMMY_NODE_ID }
123 pub fn poly_trait_ref(&self, span
: Span
, path
: ast
::Path
) -> ast
::PolyTraitRef
{
125 bound_generic_params
: Vec
::new(),
126 trait_ref
: self.trait_ref(path
),
131 pub fn trait_bound(&self, path
: ast
::Path
) -> ast
::GenericBound
{
132 ast
::GenericBound
::Trait(
133 self.poly_trait_ref(path
.span
, path
),
134 ast
::TraitBoundModifier
::None
,
138 pub fn lifetime(&self, span
: Span
, ident
: Ident
) -> ast
::Lifetime
{
139 ast
::Lifetime { id: ast::DUMMY_NODE_ID, ident: ident.with_span_pos(span) }
146 attrs
: Vec
<ast
::Attribute
>,
147 bounds
: ast
::GenericBounds
,
148 ) -> ast
::GenericParam
{
149 let lifetime
= self.lifetime(span
, ident
);
151 ident
: lifetime
.ident
,
155 kind
: ast
::GenericParamKind
::Lifetime
,
156 is_placeholder
: false,
160 pub fn stmt_expr(&self, expr
: P
<ast
::Expr
>) -> ast
::Stmt
{
162 id
: ast
::DUMMY_NODE_ID
,
164 kind
: ast
::StmtKind
::Expr(expr
),
169 pub fn stmt_let(&self, sp
: Span
, mutbl
: bool
, ident
: Ident
, ex
: P
<ast
::Expr
>) -> ast
::Stmt
{
171 let binding_mode
= ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
);
172 self.pat_ident_binding_mode(sp
, ident
, binding_mode
)
174 self.pat_ident(sp
, ident
)
176 let local
= P(ast
::Local
{
180 id
: ast
::DUMMY_NODE_ID
,
182 attrs
: AttrVec
::new(),
185 id
: ast
::DUMMY_NODE_ID
,
186 kind
: ast
::StmtKind
::Local(local
),
192 // Generates `let _: Type;`, which is usually used for type assertions.
193 pub fn stmt_let_type_only(&self, span
: Span
, ty
: P
<ast
::Ty
>) -> ast
::Stmt
{
194 let local
= P(ast
::Local
{
195 pat
: self.pat_wild(span
),
198 id
: ast
::DUMMY_NODE_ID
,
200 attrs
: AttrVec
::new(),
202 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span, tokens: None }
205 pub fn stmt_item(&self, sp
: Span
, item
: P
<ast
::Item
>) -> ast
::Stmt
{
207 id
: ast
::DUMMY_NODE_ID
,
208 kind
: ast
::StmtKind
::Item(item
),
214 pub fn block_expr(&self, expr
: P
<ast
::Expr
>) -> P
<ast
::Block
> {
218 id
: ast
::DUMMY_NODE_ID
,
220 kind
: ast
::StmtKind
::Expr(expr
),
225 pub fn block(&self, span
: Span
, stmts
: Vec
<ast
::Stmt
>) -> P
<ast
::Block
> {
228 id
: ast
::DUMMY_NODE_ID
,
229 rules
: BlockCheckMode
::Default
,
235 pub fn expr(&self, span
: Span
, kind
: ast
::ExprKind
) -> P
<ast
::Expr
> {
236 P(ast
::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new(), tokens: None }
)
239 pub fn expr_path(&self, path
: ast
::Path
) -> P
<ast
::Expr
> {
240 self.expr(path
.span
, ast
::ExprKind
::Path(None
, path
))
243 pub fn expr_ident(&self, span
: Span
, id
: Ident
) -> P
<ast
::Expr
> {
244 self.expr_path(self.path_ident(span
, id
))
246 pub fn expr_self(&self, span
: Span
) -> P
<ast
::Expr
> {
247 self.expr_ident(span
, Ident
::with_dummy_span(kw
::SelfLower
))
257 self.expr(sp
, ast
::ExprKind
::Binary(Spanned { node: op, span: sp }
, lhs
, rhs
))
260 pub fn expr_deref(&self, sp
: Span
, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
261 self.expr(sp
, ast
::ExprKind
::Unary(UnOp
::Deref
, e
))
264 pub fn expr_addr_of(&self, sp
: Span
, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
265 self.expr(sp
, ast
::ExprKind
::AddrOf(ast
::BorrowKind
::Ref
, ast
::Mutability
::Not
, e
))
272 args
: Vec
<P
<ast
::Expr
>>,
274 self.expr(span
, ast
::ExprKind
::Call(expr
, args
))
276 pub fn expr_call_ident(&self, span
: Span
, id
: Ident
, args
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
277 self.expr(span
, ast
::ExprKind
::Call(self.expr_ident(span
, id
), args
))
279 pub fn expr_call_global(
283 args
: Vec
<P
<ast
::Expr
>>,
285 let pathexpr
= self.expr_path(self.path_global(sp
, fn_path
));
286 self.expr_call(sp
, pathexpr
, args
)
288 pub fn expr_method_call(
293 mut args
: Vec
<P
<ast
::Expr
>>,
295 args
.insert(0, expr
);
296 let segment
= ast
::PathSegment
::from_ident(ident
.with_span_pos(span
));
297 self.expr(span
, ast
::ExprKind
::MethodCall(segment
, args
, span
))
299 pub fn expr_block(&self, b
: P
<ast
::Block
>) -> P
<ast
::Expr
> {
300 self.expr(b
.span
, ast
::ExprKind
::Block(b
, None
))
302 pub fn field_imm(&self, span
: Span
, ident
: Ident
, e
: P
<ast
::Expr
>) -> ast
::Field
{
304 ident
: ident
.with_span_pos(span
),
308 attrs
: AttrVec
::new(),
309 id
: ast
::DUMMY_NODE_ID
,
310 is_placeholder
: false,
317 fields
: Vec
<ast
::Field
>,
319 self.expr(span
, ast
::ExprKind
::Struct(path
, fields
, None
))
321 pub fn expr_struct_ident(
325 fields
: Vec
<ast
::Field
>,
327 self.expr_struct(span
, self.path_ident(span
, id
), fields
)
330 pub fn expr_lit(&self, span
: Span
, lit_kind
: ast
::LitKind
) -> P
<ast
::Expr
> {
331 let lit
= ast
::Lit
::from_lit_kind(lit_kind
, span
);
332 self.expr(span
, ast
::ExprKind
::Lit(lit
))
334 pub fn expr_usize(&self, span
: Span
, i
: usize) -> P
<ast
::Expr
> {
337 ast
::LitKind
::Int(i
as u128
, ast
::LitIntType
::Unsigned(ast
::UintTy
::Usize
)),
340 pub fn expr_u32(&self, sp
: Span
, u
: u32) -> P
<ast
::Expr
> {
341 self.expr_lit(sp
, ast
::LitKind
::Int(u
as u128
, ast
::LitIntType
::Unsigned(ast
::UintTy
::U32
)))
343 pub fn expr_bool(&self, sp
: Span
, value
: bool
) -> P
<ast
::Expr
> {
344 self.expr_lit(sp
, ast
::LitKind
::Bool(value
))
347 pub fn expr_vec(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
348 self.expr(sp
, ast
::ExprKind
::Array(exprs
))
350 pub fn expr_vec_slice(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
351 self.expr_addr_of(sp
, self.expr_vec(sp
, exprs
))
353 pub fn expr_str(&self, sp
: Span
, s
: Symbol
) -> P
<ast
::Expr
> {
354 self.expr_lit(sp
, ast
::LitKind
::Str(s
, ast
::StrStyle
::Cooked
))
357 pub fn expr_cast(&self, sp
: Span
, expr
: P
<ast
::Expr
>, ty
: P
<ast
::Ty
>) -> P
<ast
::Expr
> {
358 self.expr(sp
, ast
::ExprKind
::Cast(expr
, ty
))
361 pub fn expr_some(&self, sp
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
362 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::Some
]);
363 self.expr_call_global(sp
, some
, vec
![expr
])
366 pub fn expr_tuple(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
367 self.expr(sp
, ast
::ExprKind
::Tup(exprs
))
370 pub fn expr_fail(&self, span
: Span
, msg
: Symbol
) -> P
<ast
::Expr
> {
371 self.expr_call_global(
373 [sym
::std
, sym
::rt
, sym
::begin_panic
].iter().map(|s
| Ident
::new(*s
, span
)).collect(),
374 vec
![self.expr_str(span
, msg
)],
378 pub fn expr_unreachable(&self, span
: Span
) -> P
<ast
::Expr
> {
379 self.expr_fail(span
, Symbol
::intern("internal error: entered unreachable code"))
382 pub fn expr_ok(&self, sp
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
383 let ok
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
384 self.expr_call_global(sp
, ok
, vec
![expr
])
387 pub fn expr_try(&self, sp
: Span
, head
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
388 let ok
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
389 let ok_path
= self.path_global(sp
, ok
);
390 let err
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Err
]);
391 let err_path
= self.path_global(sp
, err
);
393 let binding_variable
= Ident
::new(sym
::__try_var
, sp
);
394 let binding_pat
= self.pat_ident(sp
, binding_variable
);
395 let binding_expr
= self.expr_ident(sp
, binding_variable
);
397 // `Ok(__try_var)` pattern
398 let ok_pat
= self.pat_tuple_struct(sp
, ok_path
, vec
![binding_pat
.clone()]);
400 // `Err(__try_var)` (pattern and expression respectively)
401 let err_pat
= self.pat_tuple_struct(sp
, err_path
.clone(), vec
![binding_pat
]);
403 self.expr_call(sp
, self.expr_path(err_path
), vec
![binding_expr
.clone()]);
404 // `return Err(__try_var)`
405 let err_expr
= self.expr(sp
, ast
::ExprKind
::Ret(Some(err_inner_expr
)));
407 // `Ok(__try_var) => __try_var`
408 let ok_arm
= self.arm(sp
, ok_pat
, binding_expr
);
409 // `Err(__try_var) => return Err(__try_var)`
410 let err_arm
= self.arm(sp
, err_pat
, err_expr
);
412 // `match head { Ok() => ..., Err() => ... }`
413 self.expr_match(sp
, head
, vec
![ok_arm
, err_arm
])
416 pub fn pat(&self, span
: Span
, kind
: PatKind
) -> P
<ast
::Pat
> {
417 P(ast
::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None }
)
419 pub fn pat_wild(&self, span
: Span
) -> P
<ast
::Pat
> {
420 self.pat(span
, PatKind
::Wild
)
422 pub fn pat_lit(&self, span
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Pat
> {
423 self.pat(span
, PatKind
::Lit(expr
))
425 pub fn pat_ident(&self, span
: Span
, ident
: Ident
) -> P
<ast
::Pat
> {
426 let binding_mode
= ast
::BindingMode
::ByValue(ast
::Mutability
::Not
);
427 self.pat_ident_binding_mode(span
, ident
, binding_mode
)
430 pub fn pat_ident_binding_mode(
434 bm
: ast
::BindingMode
,
436 let pat
= PatKind
::Ident(bm
, ident
.with_span_pos(span
), None
);
439 pub fn pat_path(&self, span
: Span
, path
: ast
::Path
) -> P
<ast
::Pat
> {
440 self.pat(span
, PatKind
::Path(None
, path
))
442 pub fn pat_tuple_struct(
446 subpats
: Vec
<P
<ast
::Pat
>>,
448 self.pat(span
, PatKind
::TupleStruct(path
, subpats
))
454 field_pats
: Vec
<ast
::FieldPat
>,
456 self.pat(span
, PatKind
::Struct(path
, field_pats
, false))
458 pub fn pat_tuple(&self, span
: Span
, pats
: Vec
<P
<ast
::Pat
>>) -> P
<ast
::Pat
> {
459 self.pat(span
, PatKind
::Tuple(pats
))
462 pub fn pat_some(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
463 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::Some
]);
464 let path
= self.path_global(span
, some
);
465 self.pat_tuple_struct(span
, path
, vec
![pat
])
468 pub fn pat_none(&self, span
: Span
) -> P
<ast
::Pat
> {
469 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::None
]);
470 let path
= self.path_global(span
, some
);
471 self.pat_path(span
, path
)
474 pub fn pat_ok(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
475 let some
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
476 let path
= self.path_global(span
, some
);
477 self.pat_tuple_struct(span
, path
, vec
![pat
])
480 pub fn pat_err(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
481 let some
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Err
]);
482 let path
= self.path_global(span
, some
);
483 self.pat_tuple_struct(span
, path
, vec
![pat
])
486 pub fn arm(&self, span
: Span
, pat
: P
<ast
::Pat
>, expr
: P
<ast
::Expr
>) -> ast
::Arm
{
493 id
: ast
::DUMMY_NODE_ID
,
494 is_placeholder
: false,
498 pub fn arm_unreachable(&self, span
: Span
) -> ast
::Arm
{
499 self.arm(span
, self.pat_wild(span
), self.expr_unreachable(span
))
502 pub fn expr_match(&self, span
: Span
, arg
: P
<ast
::Expr
>, arms
: Vec
<ast
::Arm
>) -> P
<Expr
> {
503 self.expr(span
, ast
::ExprKind
::Match(arg
, arms
))
511 els
: Option
<P
<ast
::Expr
>>,
513 let els
= els
.map(|x
| self.expr_block(self.block_expr(x
)));
514 self.expr(span
, ast
::ExprKind
::If(cond
, self.block_expr(then
), els
))
517 pub fn lambda_fn_decl(
520 fn_decl
: P
<ast
::FnDecl
>,
526 ast
::ExprKind
::Closure(
529 ast
::Movability
::Movable
,
537 pub fn lambda(&self, span
: Span
, ids
: Vec
<Ident
>, body
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
538 let fn_decl
= self.fn_decl(
539 ids
.iter().map(|id
| self.param(span
, *id
, self.ty(span
, ast
::TyKind
::Infer
))).collect(),
540 ast
::FnRetTy
::Default(span
),
543 // FIXME -- We are using `span` as the span of the `|...|`
544 // part of the lambda, but it probably (maybe?) corresponds to
545 // the entire lambda body. Probably we should extend the API
546 // here, but that's not entirely clear.
549 ast
::ExprKind
::Closure(
552 ast
::Movability
::Movable
,
560 pub fn lambda0(&self, span
: Span
, body
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
561 self.lambda(span
, Vec
::new(), body
)
564 pub fn lambda1(&self, span
: Span
, body
: P
<ast
::Expr
>, ident
: Ident
) -> P
<ast
::Expr
> {
565 self.lambda(span
, vec
![ident
], body
)
568 pub fn lambda_stmts_1(&self, span
: Span
, stmts
: Vec
<ast
::Stmt
>, ident
: Ident
) -> P
<ast
::Expr
> {
569 self.lambda1(span
, self.expr_block(self.block(span
, stmts
)), ident
)
572 pub fn param(&self, span
: Span
, ident
: Ident
, ty
: P
<ast
::Ty
>) -> ast
::Param
{
573 let arg_pat
= self.pat_ident(span
, ident
);
575 attrs
: AttrVec
::default(),
576 id
: ast
::DUMMY_NODE_ID
,
580 is_placeholder
: false,
584 // FIXME: unused `self`
585 pub fn fn_decl(&self, inputs
: Vec
<ast
::Param
>, output
: ast
::FnRetTy
) -> P
<ast
::FnDecl
> {
586 P(ast
::FnDecl { inputs, output }
)
593 attrs
: Vec
<ast
::Attribute
>,
596 // FIXME: Would be nice if our generated code didn't violate
597 // Rust coding conventions
601 id
: ast
::DUMMY_NODE_ID
,
603 vis
: ast
::Visibility
{
604 span
: span
.shrink_to_lo(),
605 kind
: ast
::VisibilityKind
::Inherited
,
613 pub fn variant(&self, span
: Span
, ident
: Ident
, tys
: Vec
<P
<ast
::Ty
>>) -> ast
::Variant
{
614 let vis_span
= span
.shrink_to_lo();
615 let fields
: Vec
<_
> = tys
617 .map(|ty
| ast
::StructField
{
621 vis
: ast
::Visibility
{
623 kind
: ast
::VisibilityKind
::Inherited
,
627 id
: ast
::DUMMY_NODE_ID
,
628 is_placeholder
: false,
632 let vdata
= if fields
.is_empty() {
633 ast
::VariantData
::Unit(ast
::DUMMY_NODE_ID
)
635 ast
::VariantData
::Tuple(fields
, ast
::DUMMY_NODE_ID
)
642 id
: ast
::DUMMY_NODE_ID
,
644 vis
: ast
::Visibility
{
646 kind
: ast
::VisibilityKind
::Inherited
,
650 is_placeholder
: false,
659 mutbl
: ast
::Mutability
,
662 self.item(span
, name
, Vec
::new(), ast
::ItemKind
::Static(ty
, mutbl
, Some(expr
)))
672 let def
= ast
::Defaultness
::Final
;
673 self.item(span
, name
, Vec
::new(), ast
::ItemKind
::Const(def
, ty
, Some(expr
)))
676 pub fn attribute(&self, mi
: ast
::MetaItem
) -> ast
::Attribute
{
677 attr
::mk_attr_outer(mi
)
680 pub fn meta_word(&self, sp
: Span
, w
: Symbol
) -> ast
::MetaItem
{
681 attr
::mk_word_item(Ident
::new(w
, sp
))