1 use crate::base
::ExtCtxt
;
3 use rustc_span
::source_map
::{respan, Spanned}
;
4 use rustc_span
::symbol
::{kw, sym, Symbol}
;
5 use syntax
::ast
::{self, AttrVec, BlockCheckMode, Expr, Ident, PatKind, UnOp}
;
11 impl<'a
> ExtCtxt
<'a
> {
12 pub fn path(&self, span
: Span
, strs
: Vec
<ast
::Ident
>) -> ast
::Path
{
13 self.path_all(span
, false, strs
, vec
![])
15 pub fn path_ident(&self, span
: Span
, id
: ast
::Ident
) -> ast
::Path
{
16 self.path(span
, vec
![id
])
18 pub fn path_global(&self, span
: Span
, strs
: Vec
<ast
::Ident
>) -> ast
::Path
{
19 self.path_all(span
, true, strs
, vec
![])
25 mut idents
: Vec
<ast
::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 ast
::AngleBracketedArgs { args, constraints: Vec::new(), span }
.into()
43 segments
.push(ast
::PathSegment
{
44 ident
: last_ident
.with_span_pos(span
),
45 id
: ast
::DUMMY_NODE_ID
,
48 ast
::Path { span, segments }
51 pub fn ty_mt(&self, ty
: P
<ast
::Ty
>, mutbl
: ast
::Mutability
) -> ast
::MutTy
{
52 ast
::MutTy { ty, mutbl }
55 pub fn ty(&self, span
: Span
, kind
: ast
::TyKind
) -> P
<ast
::Ty
> {
56 P(ast
::Ty { id: ast::DUMMY_NODE_ID, span, kind }
)
59 pub fn ty_path(&self, path
: ast
::Path
) -> P
<ast
::Ty
> {
60 self.ty(path
.span
, ast
::TyKind
::Path(None
, path
))
63 // Might need to take bounds as an argument in the future, if you ever want
64 // to generate a bounded existential trait type.
65 pub fn ty_ident(&self, span
: Span
, ident
: ast
::Ident
) -> P
<ast
::Ty
> {
66 self.ty_path(self.path_ident(span
, ident
))
69 pub fn anon_const(&self, span
: Span
, kind
: ast
::ExprKind
) -> ast
::AnonConst
{
71 id
: ast
::DUMMY_NODE_ID
,
72 value
: P(ast
::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new() }
),
76 pub fn const_ident(&self, span
: Span
, ident
: ast
::Ident
) -> ast
::AnonConst
{
77 self.anon_const(span
, ast
::ExprKind
::Path(None
, self.path_ident(span
, ident
)))
84 lifetime
: Option
<ast
::Lifetime
>,
85 mutbl
: ast
::Mutability
,
87 self.ty(span
, ast
::TyKind
::Rptr(lifetime
, self.ty_mt(ty
, mutbl
)))
90 pub fn ty_ptr(&self, span
: Span
, ty
: P
<ast
::Ty
>, mutbl
: ast
::Mutability
) -> P
<ast
::Ty
> {
91 self.ty(span
, ast
::TyKind
::Ptr(self.ty_mt(ty
, mutbl
)))
98 attrs
: Vec
<ast
::Attribute
>,
99 bounds
: ast
::GenericBounds
,
100 default: Option
<P
<ast
::Ty
>>,
101 ) -> ast
::GenericParam
{
103 ident
: ident
.with_span_pos(span
),
104 id
: ast
::DUMMY_NODE_ID
,
107 kind
: ast
::GenericParamKind
::Type { default }
,
108 is_placeholder
: false,
112 pub fn trait_ref(&self, path
: ast
::Path
) -> ast
::TraitRef
{
113 ast
::TraitRef { path, ref_id: ast::DUMMY_NODE_ID }
116 pub fn poly_trait_ref(&self, span
: Span
, path
: ast
::Path
) -> ast
::PolyTraitRef
{
118 bound_generic_params
: Vec
::new(),
119 trait_ref
: self.trait_ref(path
),
124 pub fn trait_bound(&self, path
: ast
::Path
) -> ast
::GenericBound
{
125 ast
::GenericBound
::Trait(
126 self.poly_trait_ref(path
.span
, path
),
127 ast
::TraitBoundModifier
::None
,
131 pub fn lifetime(&self, span
: Span
, ident
: ast
::Ident
) -> ast
::Lifetime
{
132 ast
::Lifetime { id: ast::DUMMY_NODE_ID, ident: ident.with_span_pos(span) }
139 attrs
: Vec
<ast
::Attribute
>,
140 bounds
: ast
::GenericBounds
,
141 ) -> ast
::GenericParam
{
142 let lifetime
= self.lifetime(span
, ident
);
144 ident
: lifetime
.ident
,
148 kind
: ast
::GenericParamKind
::Lifetime
,
149 is_placeholder
: false,
153 pub fn stmt_expr(&self, expr
: P
<ast
::Expr
>) -> ast
::Stmt
{
154 ast
::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) }
165 let binding_mode
= ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
);
166 self.pat_ident_binding_mode(sp
, ident
, binding_mode
)
168 self.pat_ident(sp
, ident
)
170 let local
= P(ast
::Local
{
174 id
: ast
::DUMMY_NODE_ID
,
176 attrs
: AttrVec
::new(),
178 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
181 // Generates `let _: Type;`, which is usually used for type assertions.
182 pub fn stmt_let_type_only(&self, span
: Span
, ty
: P
<ast
::Ty
>) -> ast
::Stmt
{
183 let local
= P(ast
::Local
{
184 pat
: self.pat_wild(span
),
187 id
: ast
::DUMMY_NODE_ID
,
189 attrs
: AttrVec
::new(),
191 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span }
194 pub fn stmt_item(&self, sp
: Span
, item
: P
<ast
::Item
>) -> ast
::Stmt
{
195 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp }
198 pub fn block_expr(&self, expr
: P
<ast
::Expr
>) -> P
<ast
::Block
> {
202 id
: ast
::DUMMY_NODE_ID
,
204 kind
: ast
::StmtKind
::Expr(expr
),
208 pub fn block(&self, span
: Span
, stmts
: Vec
<ast
::Stmt
>) -> P
<ast
::Block
> {
209 P(ast
::Block { stmts, id: ast::DUMMY_NODE_ID, rules: BlockCheckMode::Default, span }
)
212 pub fn expr(&self, span
: Span
, kind
: ast
::ExprKind
) -> P
<ast
::Expr
> {
213 P(ast
::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new() }
)
216 pub fn expr_path(&self, path
: ast
::Path
) -> P
<ast
::Expr
> {
217 self.expr(path
.span
, ast
::ExprKind
::Path(None
, path
))
220 pub fn expr_ident(&self, span
: Span
, id
: ast
::Ident
) -> P
<ast
::Expr
> {
221 self.expr_path(self.path_ident(span
, id
))
223 pub fn expr_self(&self, span
: Span
) -> P
<ast
::Expr
> {
224 self.expr_ident(span
, Ident
::with_dummy_span(kw
::SelfLower
))
234 self.expr(sp
, ast
::ExprKind
::Binary(Spanned { node: op, span: sp }
, lhs
, rhs
))
237 pub fn expr_deref(&self, sp
: Span
, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
238 self.expr(sp
, ast
::ExprKind
::Unary(UnOp
::Deref
, e
))
241 pub fn expr_addr_of(&self, sp
: Span
, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
242 self.expr(sp
, ast
::ExprKind
::AddrOf(ast
::BorrowKind
::Ref
, ast
::Mutability
::Not
, e
))
249 args
: Vec
<P
<ast
::Expr
>>,
251 self.expr(span
, ast
::ExprKind
::Call(expr
, args
))
253 pub fn expr_call_ident(
257 args
: Vec
<P
<ast
::Expr
>>,
259 self.expr(span
, ast
::ExprKind
::Call(self.expr_ident(span
, id
), args
))
261 pub fn expr_call_global(
264 fn_path
: Vec
<ast
::Ident
>,
265 args
: Vec
<P
<ast
::Expr
>>,
267 let pathexpr
= self.expr_path(self.path_global(sp
, fn_path
));
268 self.expr_call(sp
, pathexpr
, args
)
270 pub fn expr_method_call(
275 mut args
: Vec
<P
<ast
::Expr
>>,
277 args
.insert(0, expr
);
278 let segment
= ast
::PathSegment
::from_ident(ident
.with_span_pos(span
));
279 self.expr(span
, ast
::ExprKind
::MethodCall(segment
, args
))
281 pub fn expr_block(&self, b
: P
<ast
::Block
>) -> P
<ast
::Expr
> {
282 self.expr(b
.span
, ast
::ExprKind
::Block(b
, None
))
284 pub fn field_imm(&self, span
: Span
, ident
: Ident
, e
: P
<ast
::Expr
>) -> ast
::Field
{
286 ident
: ident
.with_span_pos(span
),
290 attrs
: AttrVec
::new(),
291 id
: ast
::DUMMY_NODE_ID
,
292 is_placeholder
: false,
299 fields
: Vec
<ast
::Field
>,
301 self.expr(span
, ast
::ExprKind
::Struct(path
, fields
, None
))
303 pub fn expr_struct_ident(
307 fields
: Vec
<ast
::Field
>,
309 self.expr_struct(span
, self.path_ident(span
, id
), fields
)
312 pub fn expr_lit(&self, span
: Span
, lit_kind
: ast
::LitKind
) -> P
<ast
::Expr
> {
313 let lit
= ast
::Lit
::from_lit_kind(lit_kind
, span
);
314 self.expr(span
, ast
::ExprKind
::Lit(lit
))
316 pub fn expr_usize(&self, span
: Span
, i
: usize) -> P
<ast
::Expr
> {
319 ast
::LitKind
::Int(i
as u128
, ast
::LitIntType
::Unsigned(ast
::UintTy
::Usize
)),
322 pub fn expr_u32(&self, sp
: Span
, u
: u32) -> P
<ast
::Expr
> {
323 self.expr_lit(sp
, ast
::LitKind
::Int(u
as u128
, ast
::LitIntType
::Unsigned(ast
::UintTy
::U32
)))
325 pub fn expr_bool(&self, sp
: Span
, value
: bool
) -> P
<ast
::Expr
> {
326 self.expr_lit(sp
, ast
::LitKind
::Bool(value
))
329 pub fn expr_vec(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
330 self.expr(sp
, ast
::ExprKind
::Array(exprs
))
332 pub fn expr_vec_slice(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
333 self.expr_addr_of(sp
, self.expr_vec(sp
, exprs
))
335 pub fn expr_str(&self, sp
: Span
, s
: Symbol
) -> P
<ast
::Expr
> {
336 self.expr_lit(sp
, ast
::LitKind
::Str(s
, ast
::StrStyle
::Cooked
))
339 pub fn expr_cast(&self, sp
: Span
, expr
: P
<ast
::Expr
>, ty
: P
<ast
::Ty
>) -> P
<ast
::Expr
> {
340 self.expr(sp
, ast
::ExprKind
::Cast(expr
, ty
))
343 pub fn expr_some(&self, sp
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
344 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::Some
]);
345 self.expr_call_global(sp
, some
, vec
![expr
])
348 pub fn expr_tuple(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
349 self.expr(sp
, ast
::ExprKind
::Tup(exprs
))
352 pub fn expr_fail(&self, span
: Span
, msg
: Symbol
) -> P
<ast
::Expr
> {
353 self.expr_call_global(
355 [sym
::std
, sym
::rt
, sym
::begin_panic
].iter().map(|s
| Ident
::new(*s
, span
)).collect(),
356 vec
![self.expr_str(span
, msg
)],
360 pub fn expr_unreachable(&self, span
: Span
) -> P
<ast
::Expr
> {
361 self.expr_fail(span
, Symbol
::intern("internal error: entered unreachable code"))
364 pub fn expr_ok(&self, sp
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
365 let ok
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
366 self.expr_call_global(sp
, ok
, vec
![expr
])
369 pub fn expr_try(&self, sp
: Span
, head
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
370 let ok
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
371 let ok_path
= self.path_global(sp
, ok
);
372 let err
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Err
]);
373 let err_path
= self.path_global(sp
, err
);
375 let binding_variable
= self.ident_of("__try_var", sp
);
376 let binding_pat
= self.pat_ident(sp
, binding_variable
);
377 let binding_expr
= self.expr_ident(sp
, binding_variable
);
379 // `Ok(__try_var)` pattern
380 let ok_pat
= self.pat_tuple_struct(sp
, ok_path
, vec
![binding_pat
.clone()]);
382 // `Err(__try_var)` (pattern and expression respectively)
383 let err_pat
= self.pat_tuple_struct(sp
, err_path
.clone(), vec
![binding_pat
]);
385 self.expr_call(sp
, self.expr_path(err_path
), vec
![binding_expr
.clone()]);
386 // `return Err(__try_var)`
387 let err_expr
= self.expr(sp
, ast
::ExprKind
::Ret(Some(err_inner_expr
)));
389 // `Ok(__try_var) => __try_var`
390 let ok_arm
= self.arm(sp
, ok_pat
, binding_expr
);
391 // `Err(__try_var) => return Err(__try_var)`
392 let err_arm
= self.arm(sp
, err_pat
, err_expr
);
394 // `match head { Ok() => ..., Err() => ... }`
395 self.expr_match(sp
, head
, vec
![ok_arm
, err_arm
])
398 pub fn pat(&self, span
: Span
, kind
: PatKind
) -> P
<ast
::Pat
> {
399 P(ast
::Pat { id: ast::DUMMY_NODE_ID, kind, span }
)
401 pub fn pat_wild(&self, span
: Span
) -> P
<ast
::Pat
> {
402 self.pat(span
, PatKind
::Wild
)
404 pub fn pat_lit(&self, span
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Pat
> {
405 self.pat(span
, PatKind
::Lit(expr
))
407 pub fn pat_ident(&self, span
: Span
, ident
: ast
::Ident
) -> P
<ast
::Pat
> {
408 let binding_mode
= ast
::BindingMode
::ByValue(ast
::Mutability
::Not
);
409 self.pat_ident_binding_mode(span
, ident
, binding_mode
)
412 pub fn pat_ident_binding_mode(
416 bm
: ast
::BindingMode
,
418 let pat
= PatKind
::Ident(bm
, ident
.with_span_pos(span
), None
);
421 pub fn pat_path(&self, span
: Span
, path
: ast
::Path
) -> P
<ast
::Pat
> {
422 self.pat(span
, PatKind
::Path(None
, path
))
424 pub fn pat_tuple_struct(
428 subpats
: Vec
<P
<ast
::Pat
>>,
430 self.pat(span
, PatKind
::TupleStruct(path
, subpats
))
436 field_pats
: Vec
<ast
::FieldPat
>,
438 self.pat(span
, PatKind
::Struct(path
, field_pats
, false))
440 pub fn pat_tuple(&self, span
: Span
, pats
: Vec
<P
<ast
::Pat
>>) -> P
<ast
::Pat
> {
441 self.pat(span
, PatKind
::Tuple(pats
))
444 pub fn pat_some(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
445 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::Some
]);
446 let path
= self.path_global(span
, some
);
447 self.pat_tuple_struct(span
, path
, vec
![pat
])
450 pub fn pat_none(&self, span
: Span
) -> P
<ast
::Pat
> {
451 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::None
]);
452 let path
= self.path_global(span
, some
);
453 self.pat_path(span
, path
)
456 pub fn pat_ok(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
457 let some
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
458 let path
= self.path_global(span
, some
);
459 self.pat_tuple_struct(span
, path
, vec
![pat
])
462 pub fn pat_err(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
463 let some
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Err
]);
464 let path
= self.path_global(span
, some
);
465 self.pat_tuple_struct(span
, path
, vec
![pat
])
468 pub fn arm(&self, span
: Span
, pat
: P
<ast
::Pat
>, expr
: P
<ast
::Expr
>) -> ast
::Arm
{
475 id
: ast
::DUMMY_NODE_ID
,
476 is_placeholder
: false,
480 pub fn arm_unreachable(&self, span
: Span
) -> ast
::Arm
{
481 self.arm(span
, self.pat_wild(span
), self.expr_unreachable(span
))
484 pub fn expr_match(&self, span
: Span
, arg
: P
<ast
::Expr
>, arms
: Vec
<ast
::Arm
>) -> P
<Expr
> {
485 self.expr(span
, ast
::ExprKind
::Match(arg
, arms
))
493 els
: Option
<P
<ast
::Expr
>>,
495 let els
= els
.map(|x
| self.expr_block(self.block_expr(x
)));
496 self.expr(span
, ast
::ExprKind
::If(cond
, self.block_expr(then
), els
))
499 pub fn lambda_fn_decl(
502 fn_decl
: P
<ast
::FnDecl
>,
508 ast
::ExprKind
::Closure(
510 ast
::IsAsync
::NotAsync
,
511 ast
::Movability
::Movable
,
519 pub fn lambda(&self, span
: Span
, ids
: Vec
<ast
::Ident
>, body
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
520 let fn_decl
= self.fn_decl(
521 ids
.iter().map(|id
| self.param(span
, *id
, self.ty(span
, ast
::TyKind
::Infer
))).collect(),
522 ast
::FunctionRetTy
::Default(span
),
525 // FIXME -- We are using `span` as the span of the `|...|`
526 // part of the lambda, but it probably (maybe?) corresponds to
527 // the entire lambda body. Probably we should extend the API
528 // here, but that's not entirely clear.
531 ast
::ExprKind
::Closure(
533 ast
::IsAsync
::NotAsync
,
534 ast
::Movability
::Movable
,
542 pub fn lambda0(&self, span
: Span
, body
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
543 self.lambda(span
, Vec
::new(), body
)
546 pub fn lambda1(&self, span
: Span
, body
: P
<ast
::Expr
>, ident
: ast
::Ident
) -> P
<ast
::Expr
> {
547 self.lambda(span
, vec
![ident
], body
)
550 pub fn lambda_stmts_1(
553 stmts
: Vec
<ast
::Stmt
>,
556 self.lambda1(span
, self.expr_block(self.block(span
, stmts
)), ident
)
559 pub fn param(&self, span
: Span
, ident
: ast
::Ident
, ty
: P
<ast
::Ty
>) -> ast
::Param
{
560 let arg_pat
= self.pat_ident(span
, ident
);
562 attrs
: AttrVec
::default(),
563 id
: ast
::DUMMY_NODE_ID
,
567 is_placeholder
: false,
571 // FIXME: unused `self`
572 pub fn fn_decl(&self, inputs
: Vec
<ast
::Param
>, output
: ast
::FunctionRetTy
) -> P
<ast
::FnDecl
> {
573 P(ast
::FnDecl { inputs, output }
)
580 attrs
: Vec
<ast
::Attribute
>,
583 // FIXME: Would be nice if our generated code didn't violate
584 // Rust coding conventions
588 id
: ast
::DUMMY_NODE_ID
,
590 vis
: respan(span
.shrink_to_lo(), ast
::VisibilityKind
::Inherited
),
596 pub fn variant(&self, span
: Span
, ident
: Ident
, tys
: Vec
<P
<ast
::Ty
>>) -> ast
::Variant
{
597 let vis_span
= span
.shrink_to_lo();
598 let fields
: Vec
<_
> = tys
600 .map(|ty
| ast
::StructField
{
604 vis
: respan(vis_span
, ast
::VisibilityKind
::Inherited
),
606 id
: ast
::DUMMY_NODE_ID
,
607 is_placeholder
: false,
611 let vdata
= if fields
.is_empty() {
612 ast
::VariantData
::Unit(ast
::DUMMY_NODE_ID
)
614 ast
::VariantData
::Tuple(fields
, ast
::DUMMY_NODE_ID
)
621 id
: ast
::DUMMY_NODE_ID
,
623 vis
: respan(vis_span
, ast
::VisibilityKind
::Inherited
),
625 is_placeholder
: false,
634 mutbl
: ast
::Mutability
,
637 self.item(span
, name
, Vec
::new(), ast
::ItemKind
::Static(ty
, mutbl
, expr
))
647 self.item(span
, name
, Vec
::new(), ast
::ItemKind
::Const(ty
, expr
))
650 pub fn attribute(&self, mi
: ast
::MetaItem
) -> ast
::Attribute
{
651 attr
::mk_attr_outer(mi
)
654 pub fn meta_word(&self, sp
: Span
, w
: ast
::Name
) -> ast
::MetaItem
{
655 attr
::mk_word_item(Ident
::new(w
, sp
))