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) }
142 pub fn stmt_expr(&self, expr
: P
<ast
::Expr
>) -> ast
::Stmt
{
143 ast
::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) }
146 pub fn stmt_let(&self, sp
: Span
, mutbl
: bool
, ident
: Ident
, ex
: P
<ast
::Expr
>) -> ast
::Stmt
{
148 let binding_mode
= ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
);
149 self.pat_ident_binding_mode(sp
, ident
, binding_mode
)
151 self.pat_ident(sp
, ident
)
153 let local
= P(ast
::Local
{
157 id
: ast
::DUMMY_NODE_ID
,
159 attrs
: AttrVec
::new(),
162 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
165 // Generates `let _: Type;`, which is usually used for type assertions.
166 pub fn stmt_let_type_only(&self, span
: Span
, ty
: P
<ast
::Ty
>) -> ast
::Stmt
{
167 let local
= P(ast
::Local
{
168 pat
: self.pat_wild(span
),
171 id
: ast
::DUMMY_NODE_ID
,
173 attrs
: AttrVec
::new(),
176 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span }
179 pub fn stmt_item(&self, sp
: Span
, item
: P
<ast
::Item
>) -> ast
::Stmt
{
180 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp }
183 pub fn block_expr(&self, expr
: P
<ast
::Expr
>) -> P
<ast
::Block
> {
187 id
: ast
::DUMMY_NODE_ID
,
189 kind
: ast
::StmtKind
::Expr(expr
),
193 pub fn block(&self, span
: Span
, stmts
: Vec
<ast
::Stmt
>) -> P
<ast
::Block
> {
196 id
: ast
::DUMMY_NODE_ID
,
197 rules
: BlockCheckMode
::Default
,
203 pub fn expr(&self, span
: Span
, kind
: ast
::ExprKind
) -> P
<ast
::Expr
> {
204 P(ast
::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new(), tokens: None }
)
207 pub fn expr_path(&self, path
: ast
::Path
) -> P
<ast
::Expr
> {
208 self.expr(path
.span
, ast
::ExprKind
::Path(None
, path
))
211 pub fn expr_ident(&self, span
: Span
, id
: Ident
) -> P
<ast
::Expr
> {
212 self.expr_path(self.path_ident(span
, id
))
214 pub fn expr_self(&self, span
: Span
) -> P
<ast
::Expr
> {
215 self.expr_ident(span
, Ident
::with_dummy_span(kw
::SelfLower
))
225 self.expr(sp
, ast
::ExprKind
::Binary(Spanned { node: op, span: sp }
, lhs
, rhs
))
228 pub fn expr_deref(&self, sp
: Span
, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
229 self.expr(sp
, ast
::ExprKind
::Unary(UnOp
::Deref
, e
))
232 pub fn expr_addr_of(&self, sp
: Span
, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
233 self.expr(sp
, ast
::ExprKind
::AddrOf(ast
::BorrowKind
::Ref
, ast
::Mutability
::Not
, e
))
240 args
: Vec
<P
<ast
::Expr
>>,
242 self.expr(span
, ast
::ExprKind
::Call(expr
, args
))
244 pub fn expr_call_ident(&self, span
: Span
, id
: Ident
, args
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
245 self.expr(span
, ast
::ExprKind
::Call(self.expr_ident(span
, id
), args
))
247 pub fn expr_call_global(
251 args
: Vec
<P
<ast
::Expr
>>,
253 let pathexpr
= self.expr_path(self.path_global(sp
, fn_path
));
254 self.expr_call(sp
, pathexpr
, args
)
256 pub fn expr_block(&self, b
: P
<ast
::Block
>) -> P
<ast
::Expr
> {
257 self.expr(b
.span
, ast
::ExprKind
::Block(b
, None
))
259 pub fn field_imm(&self, span
: Span
, ident
: Ident
, e
: P
<ast
::Expr
>) -> ast
::ExprField
{
261 ident
: ident
.with_span_pos(span
),
265 attrs
: AttrVec
::new(),
266 id
: ast
::DUMMY_NODE_ID
,
267 is_placeholder
: false,
274 fields
: Vec
<ast
::ExprField
>,
278 ast
::ExprKind
::Struct(P(ast
::StructExpr
{
282 rest
: ast
::StructRest
::None
,
286 pub fn expr_struct_ident(
290 fields
: Vec
<ast
::ExprField
>,
292 self.expr_struct(span
, self.path_ident(span
, id
), fields
)
295 pub fn expr_lit(&self, span
: Span
, lit_kind
: ast
::LitKind
) -> P
<ast
::Expr
> {
296 let lit
= ast
::Lit
::from_lit_kind(lit_kind
, span
);
297 self.expr(span
, ast
::ExprKind
::Lit(lit
))
299 pub fn expr_usize(&self, span
: Span
, i
: usize) -> P
<ast
::Expr
> {
302 ast
::LitKind
::Int(i
as u128
, ast
::LitIntType
::Unsigned(ast
::UintTy
::Usize
)),
305 pub fn expr_u32(&self, sp
: Span
, u
: u32) -> P
<ast
::Expr
> {
306 self.expr_lit(sp
, ast
::LitKind
::Int(u
as u128
, ast
::LitIntType
::Unsigned(ast
::UintTy
::U32
)))
308 pub fn expr_bool(&self, sp
: Span
, value
: bool
) -> P
<ast
::Expr
> {
309 self.expr_lit(sp
, ast
::LitKind
::Bool(value
))
312 pub fn expr_vec(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
313 self.expr(sp
, ast
::ExprKind
::Array(exprs
))
315 pub fn expr_vec_slice(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
316 self.expr_addr_of(sp
, self.expr_vec(sp
, exprs
))
318 pub fn expr_str(&self, sp
: Span
, s
: Symbol
) -> P
<ast
::Expr
> {
319 self.expr_lit(sp
, ast
::LitKind
::Str(s
, ast
::StrStyle
::Cooked
))
322 pub fn expr_cast(&self, sp
: Span
, expr
: P
<ast
::Expr
>, ty
: P
<ast
::Ty
>) -> P
<ast
::Expr
> {
323 self.expr(sp
, ast
::ExprKind
::Cast(expr
, ty
))
326 pub fn expr_some(&self, sp
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
327 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::Some
]);
328 self.expr_call_global(sp
, some
, vec
![expr
])
331 pub fn expr_tuple(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
332 self.expr(sp
, ast
::ExprKind
::Tup(exprs
))
335 pub fn expr_fail(&self, span
: Span
, msg
: Symbol
) -> P
<ast
::Expr
> {
336 self.expr_call_global(
338 [sym
::std
, sym
::rt
, sym
::begin_panic
].iter().map(|s
| Ident
::new(*s
, span
)).collect(),
339 vec
![self.expr_str(span
, msg
)],
343 pub fn expr_unreachable(&self, span
: Span
) -> P
<ast
::Expr
> {
344 self.expr_fail(span
, Symbol
::intern("internal error: entered unreachable code"))
347 pub fn expr_ok(&self, sp
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
348 let ok
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
349 self.expr_call_global(sp
, ok
, vec
![expr
])
352 pub fn expr_try(&self, sp
: Span
, head
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
353 let ok
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
354 let ok_path
= self.path_global(sp
, ok
);
355 let err
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Err
]);
356 let err_path
= self.path_global(sp
, err
);
358 let binding_variable
= Ident
::new(sym
::__try_var
, sp
);
359 let binding_pat
= self.pat_ident(sp
, binding_variable
);
360 let binding_expr
= self.expr_ident(sp
, binding_variable
);
362 // `Ok(__try_var)` pattern
363 let ok_pat
= self.pat_tuple_struct(sp
, ok_path
, vec
![binding_pat
.clone()]);
365 // `Err(__try_var)` (pattern and expression respectively)
366 let err_pat
= self.pat_tuple_struct(sp
, err_path
.clone(), vec
![binding_pat
]);
368 self.expr_call(sp
, self.expr_path(err_path
), vec
![binding_expr
.clone()]);
369 // `return Err(__try_var)`
370 let err_expr
= self.expr(sp
, ast
::ExprKind
::Ret(Some(err_inner_expr
)));
372 // `Ok(__try_var) => __try_var`
373 let ok_arm
= self.arm(sp
, ok_pat
, binding_expr
);
374 // `Err(__try_var) => return Err(__try_var)`
375 let err_arm
= self.arm(sp
, err_pat
, err_expr
);
377 // `match head { Ok() => ..., Err() => ... }`
378 self.expr_match(sp
, head
, vec
![ok_arm
, err_arm
])
381 pub fn pat(&self, span
: Span
, kind
: PatKind
) -> P
<ast
::Pat
> {
382 P(ast
::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None }
)
384 pub fn pat_wild(&self, span
: Span
) -> P
<ast
::Pat
> {
385 self.pat(span
, PatKind
::Wild
)
387 pub fn pat_lit(&self, span
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Pat
> {
388 self.pat(span
, PatKind
::Lit(expr
))
390 pub fn pat_ident(&self, span
: Span
, ident
: Ident
) -> P
<ast
::Pat
> {
391 let binding_mode
= ast
::BindingMode
::ByValue(ast
::Mutability
::Not
);
392 self.pat_ident_binding_mode(span
, ident
, binding_mode
)
395 pub fn pat_ident_binding_mode(
399 bm
: ast
::BindingMode
,
401 let pat
= PatKind
::Ident(bm
, ident
.with_span_pos(span
), None
);
404 pub fn pat_path(&self, span
: Span
, path
: ast
::Path
) -> P
<ast
::Pat
> {
405 self.pat(span
, PatKind
::Path(None
, path
))
407 pub fn pat_tuple_struct(
411 subpats
: Vec
<P
<ast
::Pat
>>,
413 self.pat(span
, PatKind
::TupleStruct(None
, path
, subpats
))
419 field_pats
: Vec
<ast
::PatField
>,
421 self.pat(span
, PatKind
::Struct(None
, path
, field_pats
, false))
423 pub fn pat_tuple(&self, span
: Span
, pats
: Vec
<P
<ast
::Pat
>>) -> P
<ast
::Pat
> {
424 self.pat(span
, PatKind
::Tuple(pats
))
427 pub fn pat_some(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
428 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::Some
]);
429 let path
= self.path_global(span
, some
);
430 self.pat_tuple_struct(span
, path
, vec
![pat
])
433 pub fn arm(&self, span
: Span
, pat
: P
<ast
::Pat
>, expr
: P
<ast
::Expr
>) -> ast
::Arm
{
435 attrs
: AttrVec
::new(),
440 id
: ast
::DUMMY_NODE_ID
,
441 is_placeholder
: false,
445 pub fn arm_unreachable(&self, span
: Span
) -> ast
::Arm
{
446 self.arm(span
, self.pat_wild(span
), self.expr_unreachable(span
))
449 pub fn expr_match(&self, span
: Span
, arg
: P
<ast
::Expr
>, arms
: Vec
<ast
::Arm
>) -> P
<Expr
> {
450 self.expr(span
, ast
::ExprKind
::Match(arg
, arms
))
458 els
: Option
<P
<ast
::Expr
>>,
460 let els
= els
.map(|x
| self.expr_block(self.block_expr(x
)));
461 self.expr(span
, ast
::ExprKind
::If(cond
, self.block_expr(then
), els
))
464 pub fn lambda(&self, span
: Span
, ids
: Vec
<Ident
>, body
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
465 let fn_decl
= self.fn_decl(
466 ids
.iter().map(|id
| self.param(span
, *id
, self.ty(span
, ast
::TyKind
::Infer
))).collect(),
467 ast
::FnRetTy
::Default(span
),
470 // FIXME -- We are using `span` as the span of the `|...|`
471 // part of the lambda, but it probably (maybe?) corresponds to
472 // the entire lambda body. Probably we should extend the API
473 // here, but that's not entirely clear.
476 ast
::ExprKind
::Closure(
479 ast
::Movability
::Movable
,
487 pub fn lambda0(&self, span
: Span
, body
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
488 self.lambda(span
, Vec
::new(), body
)
491 pub fn lambda1(&self, span
: Span
, body
: P
<ast
::Expr
>, ident
: Ident
) -> P
<ast
::Expr
> {
492 self.lambda(span
, vec
![ident
], body
)
495 pub fn lambda_stmts_1(&self, span
: Span
, stmts
: Vec
<ast
::Stmt
>, ident
: Ident
) -> P
<ast
::Expr
> {
496 self.lambda1(span
, self.expr_block(self.block(span
, stmts
)), ident
)
499 pub fn param(&self, span
: Span
, ident
: Ident
, ty
: P
<ast
::Ty
>) -> ast
::Param
{
500 let arg_pat
= self.pat_ident(span
, ident
);
502 attrs
: AttrVec
::default(),
503 id
: ast
::DUMMY_NODE_ID
,
507 is_placeholder
: false,
511 // FIXME: unused `self`
512 pub fn fn_decl(&self, inputs
: Vec
<ast
::Param
>, output
: ast
::FnRetTy
) -> P
<ast
::FnDecl
> {
513 P(ast
::FnDecl { inputs, output }
)
520 attrs
: Vec
<ast
::Attribute
>,
523 // FIXME: Would be nice if our generated code didn't violate
524 // Rust coding conventions
528 id
: ast
::DUMMY_NODE_ID
,
530 vis
: ast
::Visibility
{
531 span
: span
.shrink_to_lo(),
532 kind
: ast
::VisibilityKind
::Inherited
,
545 mutbl
: ast
::Mutability
,
548 self.item(span
, name
, Vec
::new(), ast
::ItemKind
::Static(ty
, mutbl
, Some(expr
)))
558 let def
= ast
::Defaultness
::Final
;
559 self.item(span
, name
, Vec
::new(), ast
::ItemKind
::Const(def
, ty
, Some(expr
)))
562 pub fn attribute(&self, mi
: ast
::MetaItem
) -> ast
::Attribute
{
563 attr
::mk_attr_outer(mi
)
566 pub fn meta_word(&self, sp
: Span
, w
: Symbol
) -> ast
::MetaItem
{
567 attr
::mk_word_item(Ident
::new(w
, sp
))