1 use crate::base
::ExtCtxt
;
3 use rustc_ast
::ast
::{self, AttrVec, BlockCheckMode, Expr, PatKind, UnOp}
;
6 use rustc_span
::source_map
::{respan, 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 }
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 }
)
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
{
161 ast
::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Expr(expr) }
164 pub fn stmt_let(&self, sp
: Span
, mutbl
: bool
, ident
: Ident
, ex
: P
<ast
::Expr
>) -> ast
::Stmt
{
166 let binding_mode
= ast
::BindingMode
::ByValue(ast
::Mutability
::Mut
);
167 self.pat_ident_binding_mode(sp
, ident
, binding_mode
)
169 self.pat_ident(sp
, ident
)
171 let local
= P(ast
::Local
{
175 id
: ast
::DUMMY_NODE_ID
,
177 attrs
: AttrVec
::new(),
179 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
182 // Generates `let _: Type;`, which is usually used for type assertions.
183 pub fn stmt_let_type_only(&self, span
: Span
, ty
: P
<ast
::Ty
>) -> ast
::Stmt
{
184 let local
= P(ast
::Local
{
185 pat
: self.pat_wild(span
),
188 id
: ast
::DUMMY_NODE_ID
,
190 attrs
: AttrVec
::new(),
192 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span }
195 pub fn stmt_item(&self, sp
: Span
, item
: P
<ast
::Item
>) -> ast
::Stmt
{
196 ast
::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp }
199 pub fn block_expr(&self, expr
: P
<ast
::Expr
>) -> P
<ast
::Block
> {
203 id
: ast
::DUMMY_NODE_ID
,
205 kind
: ast
::StmtKind
::Expr(expr
),
209 pub fn block(&self, span
: Span
, stmts
: Vec
<ast
::Stmt
>) -> P
<ast
::Block
> {
210 P(ast
::Block { stmts, id: ast::DUMMY_NODE_ID, rules: BlockCheckMode::Default, span }
)
213 pub fn expr(&self, span
: Span
, kind
: ast
::ExprKind
) -> P
<ast
::Expr
> {
214 P(ast
::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new(), tokens: None }
)
217 pub fn expr_path(&self, path
: ast
::Path
) -> P
<ast
::Expr
> {
218 self.expr(path
.span
, ast
::ExprKind
::Path(None
, path
))
221 pub fn expr_ident(&self, span
: Span
, id
: Ident
) -> P
<ast
::Expr
> {
222 self.expr_path(self.path_ident(span
, id
))
224 pub fn expr_self(&self, span
: Span
) -> P
<ast
::Expr
> {
225 self.expr_ident(span
, Ident
::with_dummy_span(kw
::SelfLower
))
235 self.expr(sp
, ast
::ExprKind
::Binary(Spanned { node: op, span: sp }
, lhs
, rhs
))
238 pub fn expr_deref(&self, sp
: Span
, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
239 self.expr(sp
, ast
::ExprKind
::Unary(UnOp
::Deref
, e
))
242 pub fn expr_addr_of(&self, sp
: Span
, e
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
243 self.expr(sp
, ast
::ExprKind
::AddrOf(ast
::BorrowKind
::Ref
, ast
::Mutability
::Not
, e
))
250 args
: Vec
<P
<ast
::Expr
>>,
252 self.expr(span
, ast
::ExprKind
::Call(expr
, args
))
254 pub fn expr_call_ident(&self, span
: Span
, id
: Ident
, args
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
255 self.expr(span
, ast
::ExprKind
::Call(self.expr_ident(span
, id
), args
))
257 pub fn expr_call_global(
261 args
: Vec
<P
<ast
::Expr
>>,
263 let pathexpr
= self.expr_path(self.path_global(sp
, fn_path
));
264 self.expr_call(sp
, pathexpr
, args
)
266 pub fn expr_method_call(
271 mut args
: Vec
<P
<ast
::Expr
>>,
273 args
.insert(0, expr
);
274 let segment
= ast
::PathSegment
::from_ident(ident
.with_span_pos(span
));
275 self.expr(span
, ast
::ExprKind
::MethodCall(segment
, args
, span
))
277 pub fn expr_block(&self, b
: P
<ast
::Block
>) -> P
<ast
::Expr
> {
278 self.expr(b
.span
, ast
::ExprKind
::Block(b
, None
))
280 pub fn field_imm(&self, span
: Span
, ident
: Ident
, e
: P
<ast
::Expr
>) -> ast
::Field
{
282 ident
: ident
.with_span_pos(span
),
286 attrs
: AttrVec
::new(),
287 id
: ast
::DUMMY_NODE_ID
,
288 is_placeholder
: false,
295 fields
: Vec
<ast
::Field
>,
297 self.expr(span
, ast
::ExprKind
::Struct(path
, fields
, None
))
299 pub fn expr_struct_ident(
303 fields
: Vec
<ast
::Field
>,
305 self.expr_struct(span
, self.path_ident(span
, id
), fields
)
308 pub fn expr_lit(&self, span
: Span
, lit_kind
: ast
::LitKind
) -> P
<ast
::Expr
> {
309 let lit
= ast
::Lit
::from_lit_kind(lit_kind
, span
);
310 self.expr(span
, ast
::ExprKind
::Lit(lit
))
312 pub fn expr_usize(&self, span
: Span
, i
: usize) -> P
<ast
::Expr
> {
315 ast
::LitKind
::Int(i
as u128
, ast
::LitIntType
::Unsigned(ast
::UintTy
::Usize
)),
318 pub fn expr_u32(&self, sp
: Span
, u
: u32) -> P
<ast
::Expr
> {
319 self.expr_lit(sp
, ast
::LitKind
::Int(u
as u128
, ast
::LitIntType
::Unsigned(ast
::UintTy
::U32
)))
321 pub fn expr_bool(&self, sp
: Span
, value
: bool
) -> P
<ast
::Expr
> {
322 self.expr_lit(sp
, ast
::LitKind
::Bool(value
))
325 pub fn expr_vec(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
326 self.expr(sp
, ast
::ExprKind
::Array(exprs
))
328 pub fn expr_vec_slice(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
329 self.expr_addr_of(sp
, self.expr_vec(sp
, exprs
))
331 pub fn expr_str(&self, sp
: Span
, s
: Symbol
) -> P
<ast
::Expr
> {
332 self.expr_lit(sp
, ast
::LitKind
::Str(s
, ast
::StrStyle
::Cooked
))
335 pub fn expr_cast(&self, sp
: Span
, expr
: P
<ast
::Expr
>, ty
: P
<ast
::Ty
>) -> P
<ast
::Expr
> {
336 self.expr(sp
, ast
::ExprKind
::Cast(expr
, ty
))
339 pub fn expr_some(&self, sp
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
340 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::Some
]);
341 self.expr_call_global(sp
, some
, vec
![expr
])
344 pub fn expr_tuple(&self, sp
: Span
, exprs
: Vec
<P
<ast
::Expr
>>) -> P
<ast
::Expr
> {
345 self.expr(sp
, ast
::ExprKind
::Tup(exprs
))
348 pub fn expr_fail(&self, span
: Span
, msg
: Symbol
) -> P
<ast
::Expr
> {
349 self.expr_call_global(
351 [sym
::std
, sym
::rt
, sym
::begin_panic
].iter().map(|s
| Ident
::new(*s
, span
)).collect(),
352 vec
![self.expr_str(span
, msg
)],
356 pub fn expr_unreachable(&self, span
: Span
) -> P
<ast
::Expr
> {
357 self.expr_fail(span
, Symbol
::intern("internal error: entered unreachable code"))
360 pub fn expr_ok(&self, sp
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
361 let ok
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
362 self.expr_call_global(sp
, ok
, vec
![expr
])
365 pub fn expr_try(&self, sp
: Span
, head
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
366 let ok
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
367 let ok_path
= self.path_global(sp
, ok
);
368 let err
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Err
]);
369 let err_path
= self.path_global(sp
, err
);
371 let binding_variable
= self.ident_of("__try_var", sp
);
372 let binding_pat
= self.pat_ident(sp
, binding_variable
);
373 let binding_expr
= self.expr_ident(sp
, binding_variable
);
375 // `Ok(__try_var)` pattern
376 let ok_pat
= self.pat_tuple_struct(sp
, ok_path
, vec
![binding_pat
.clone()]);
378 // `Err(__try_var)` (pattern and expression respectively)
379 let err_pat
= self.pat_tuple_struct(sp
, err_path
.clone(), vec
![binding_pat
]);
381 self.expr_call(sp
, self.expr_path(err_path
), vec
![binding_expr
.clone()]);
382 // `return Err(__try_var)`
383 let err_expr
= self.expr(sp
, ast
::ExprKind
::Ret(Some(err_inner_expr
)));
385 // `Ok(__try_var) => __try_var`
386 let ok_arm
= self.arm(sp
, ok_pat
, binding_expr
);
387 // `Err(__try_var) => return Err(__try_var)`
388 let err_arm
= self.arm(sp
, err_pat
, err_expr
);
390 // `match head { Ok() => ..., Err() => ... }`
391 self.expr_match(sp
, head
, vec
![ok_arm
, err_arm
])
394 pub fn pat(&self, span
: Span
, kind
: PatKind
) -> P
<ast
::Pat
> {
395 P(ast
::Pat { id: ast::DUMMY_NODE_ID, kind, span }
)
397 pub fn pat_wild(&self, span
: Span
) -> P
<ast
::Pat
> {
398 self.pat(span
, PatKind
::Wild
)
400 pub fn pat_lit(&self, span
: Span
, expr
: P
<ast
::Expr
>) -> P
<ast
::Pat
> {
401 self.pat(span
, PatKind
::Lit(expr
))
403 pub fn pat_ident(&self, span
: Span
, ident
: Ident
) -> P
<ast
::Pat
> {
404 let binding_mode
= ast
::BindingMode
::ByValue(ast
::Mutability
::Not
);
405 self.pat_ident_binding_mode(span
, ident
, binding_mode
)
408 pub fn pat_ident_binding_mode(
412 bm
: ast
::BindingMode
,
414 let pat
= PatKind
::Ident(bm
, ident
.with_span_pos(span
), None
);
417 pub fn pat_path(&self, span
: Span
, path
: ast
::Path
) -> P
<ast
::Pat
> {
418 self.pat(span
, PatKind
::Path(None
, path
))
420 pub fn pat_tuple_struct(
424 subpats
: Vec
<P
<ast
::Pat
>>,
426 self.pat(span
, PatKind
::TupleStruct(path
, subpats
))
432 field_pats
: Vec
<ast
::FieldPat
>,
434 self.pat(span
, PatKind
::Struct(path
, field_pats
, false))
436 pub fn pat_tuple(&self, span
: Span
, pats
: Vec
<P
<ast
::Pat
>>) -> P
<ast
::Pat
> {
437 self.pat(span
, PatKind
::Tuple(pats
))
440 pub fn pat_some(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
441 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::Some
]);
442 let path
= self.path_global(span
, some
);
443 self.pat_tuple_struct(span
, path
, vec
![pat
])
446 pub fn pat_none(&self, span
: Span
) -> P
<ast
::Pat
> {
447 let some
= self.std_path(&[sym
::option
, sym
::Option
, sym
::None
]);
448 let path
= self.path_global(span
, some
);
449 self.pat_path(span
, path
)
452 pub fn pat_ok(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
453 let some
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Ok
]);
454 let path
= self.path_global(span
, some
);
455 self.pat_tuple_struct(span
, path
, vec
![pat
])
458 pub fn pat_err(&self, span
: Span
, pat
: P
<ast
::Pat
>) -> P
<ast
::Pat
> {
459 let some
= self.std_path(&[sym
::result
, sym
::Result
, sym
::Err
]);
460 let path
= self.path_global(span
, some
);
461 self.pat_tuple_struct(span
, path
, vec
![pat
])
464 pub fn arm(&self, span
: Span
, pat
: P
<ast
::Pat
>, expr
: P
<ast
::Expr
>) -> ast
::Arm
{
471 id
: ast
::DUMMY_NODE_ID
,
472 is_placeholder
: false,
476 pub fn arm_unreachable(&self, span
: Span
) -> ast
::Arm
{
477 self.arm(span
, self.pat_wild(span
), self.expr_unreachable(span
))
480 pub fn expr_match(&self, span
: Span
, arg
: P
<ast
::Expr
>, arms
: Vec
<ast
::Arm
>) -> P
<Expr
> {
481 self.expr(span
, ast
::ExprKind
::Match(arg
, arms
))
489 els
: Option
<P
<ast
::Expr
>>,
491 let els
= els
.map(|x
| self.expr_block(self.block_expr(x
)));
492 self.expr(span
, ast
::ExprKind
::If(cond
, self.block_expr(then
), els
))
495 pub fn lambda_fn_decl(
498 fn_decl
: P
<ast
::FnDecl
>,
504 ast
::ExprKind
::Closure(
507 ast
::Movability
::Movable
,
515 pub fn lambda(&self, span
: Span
, ids
: Vec
<Ident
>, body
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
516 let fn_decl
= self.fn_decl(
517 ids
.iter().map(|id
| self.param(span
, *id
, self.ty(span
, ast
::TyKind
::Infer
))).collect(),
518 ast
::FnRetTy
::Default(span
),
521 // FIXME -- We are using `span` as the span of the `|...|`
522 // part of the lambda, but it probably (maybe?) corresponds to
523 // the entire lambda body. Probably we should extend the API
524 // here, but that's not entirely clear.
527 ast
::ExprKind
::Closure(
530 ast
::Movability
::Movable
,
538 pub fn lambda0(&self, span
: Span
, body
: P
<ast
::Expr
>) -> P
<ast
::Expr
> {
539 self.lambda(span
, Vec
::new(), body
)
542 pub fn lambda1(&self, span
: Span
, body
: P
<ast
::Expr
>, ident
: Ident
) -> P
<ast
::Expr
> {
543 self.lambda(span
, vec
![ident
], body
)
546 pub fn lambda_stmts_1(&self, span
: Span
, stmts
: Vec
<ast
::Stmt
>, ident
: Ident
) -> P
<ast
::Expr
> {
547 self.lambda1(span
, self.expr_block(self.block(span
, stmts
)), ident
)
550 pub fn param(&self, span
: Span
, ident
: Ident
, ty
: P
<ast
::Ty
>) -> ast
::Param
{
551 let arg_pat
= self.pat_ident(span
, ident
);
553 attrs
: AttrVec
::default(),
554 id
: ast
::DUMMY_NODE_ID
,
558 is_placeholder
: false,
562 // FIXME: unused `self`
563 pub fn fn_decl(&self, inputs
: Vec
<ast
::Param
>, output
: ast
::FnRetTy
) -> P
<ast
::FnDecl
> {
564 P(ast
::FnDecl { inputs, output }
)
571 attrs
: Vec
<ast
::Attribute
>,
574 // FIXME: Would be nice if our generated code didn't violate
575 // Rust coding conventions
579 id
: ast
::DUMMY_NODE_ID
,
581 vis
: respan(span
.shrink_to_lo(), ast
::VisibilityKind
::Inherited
),
587 pub fn variant(&self, span
: Span
, ident
: Ident
, tys
: Vec
<P
<ast
::Ty
>>) -> ast
::Variant
{
588 let vis_span
= span
.shrink_to_lo();
589 let fields
: Vec
<_
> = tys
591 .map(|ty
| ast
::StructField
{
595 vis
: respan(vis_span
, ast
::VisibilityKind
::Inherited
),
597 id
: ast
::DUMMY_NODE_ID
,
598 is_placeholder
: false,
602 let vdata
= if fields
.is_empty() {
603 ast
::VariantData
::Unit(ast
::DUMMY_NODE_ID
)
605 ast
::VariantData
::Tuple(fields
, ast
::DUMMY_NODE_ID
)
612 id
: ast
::DUMMY_NODE_ID
,
614 vis
: respan(vis_span
, ast
::VisibilityKind
::Inherited
),
616 is_placeholder
: false,
625 mutbl
: ast
::Mutability
,
628 self.item(span
, name
, Vec
::new(), ast
::ItemKind
::Static(ty
, mutbl
, Some(expr
)))
638 let def
= ast
::Defaultness
::Final
;
639 self.item(span
, name
, Vec
::new(), ast
::ItemKind
::Const(def
, ty
, Some(expr
)))
642 pub fn attribute(&self, mi
: ast
::MetaItem
) -> ast
::Attribute
{
643 attr
::mk_attr_outer(mi
)
646 pub fn meta_word(&self, sp
: Span
, w
: Symbol
) -> ast
::MetaItem
{
647 attr
::mk_word_item(Ident
::new(w
, sp
))