1 use crate::base::ExtCtxt; 2 use rustc_ast::ptr::P; 3 use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp}; 4 use rustc_ast::{attr, token, util::literal}; 5 use rustc_span::source_map::Spanned; 6 use rustc_span::symbol::{kw, sym, Ident, Symbol}; 7 use rustc_span::Span; 8 use thin_vec::{thin_vec, ThinVec}; 9 10 impl<'a> ExtCtxt<'a> { path(&self, span: Span, strs: Vec<Ident>) -> ast::Path11 pub fn path(&self, span: Span, strs: Vec<Ident>) -> ast::Path { 12 self.path_all(span, false, strs, vec![]) 13 } path_ident(&self, span: Span, id: Ident) -> ast::Path14 pub fn path_ident(&self, span: Span, id: Ident) -> ast::Path { 15 self.path(span, vec![id]) 16 } path_global(&self, span: Span, strs: Vec<Ident>) -> ast::Path17 pub fn path_global(&self, span: Span, strs: Vec<Ident>) -> ast::Path { 18 self.path_all(span, true, strs, vec![]) 19 } path_all( &self, span: Span, global: bool, mut idents: Vec<Ident>, args: Vec<ast::GenericArg>, ) -> ast::Path20 pub fn path_all( 21 &self, 22 span: Span, 23 global: bool, 24 mut idents: Vec<Ident>, 25 args: Vec<ast::GenericArg>, 26 ) -> ast::Path { 27 assert!(!idents.is_empty()); 28 let add_root = global && !idents[0].is_path_segment_keyword(); 29 let mut segments = ThinVec::with_capacity(idents.len() + add_root as usize); 30 if add_root { 31 segments.push(ast::PathSegment::path_root(span)); 32 } 33 let last_ident = idents.pop().unwrap(); 34 segments.extend( 35 idents.into_iter().map(|ident| ast::PathSegment::from_ident(ident.with_span_pos(span))), 36 ); 37 let args = if !args.is_empty() { 38 let args = args.into_iter().map(ast::AngleBracketedArg::Arg).collect(); 39 Some(ast::AngleBracketedArgs { args, span }.into()) 40 } else { 41 None 42 }; 43 segments.push(ast::PathSegment { 44 ident: last_ident.with_span_pos(span), 45 id: ast::DUMMY_NODE_ID, 46 args, 47 }); 48 ast::Path { span, segments, tokens: None } 49 } 50 ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy51 pub fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy { 52 ast::MutTy { ty, mutbl } 53 } 54 ty(&self, span: Span, kind: ast::TyKind) -> P<ast::Ty>55 pub fn ty(&self, span: Span, kind: ast::TyKind) -> P<ast::Ty> { 56 P(ast::Ty { id: ast::DUMMY_NODE_ID, span, kind, tokens: None }) 57 } 58 ty_infer(&self, span: Span) -> P<ast::Ty>59 pub fn ty_infer(&self, span: Span) -> P<ast::Ty> { 60 self.ty(span, ast::TyKind::Infer) 61 } 62 ty_path(&self, path: ast::Path) -> P<ast::Ty>63 pub fn ty_path(&self, path: ast::Path) -> P<ast::Ty> { 64 self.ty(path.span, ast::TyKind::Path(None, path)) 65 } 66 67 // Might need to take bounds as an argument in the future, if you ever want 68 // to generate a bounded existential trait type. ty_ident(&self, span: Span, ident: Ident) -> P<ast::Ty>69 pub fn ty_ident(&self, span: Span, ident: Ident) -> P<ast::Ty> { 70 self.ty_path(self.path_ident(span, ident)) 71 } 72 anon_const(&self, span: Span, kind: ast::ExprKind) -> ast::AnonConst73 pub fn anon_const(&self, span: Span, kind: ast::ExprKind) -> ast::AnonConst { 74 ast::AnonConst { 75 id: ast::DUMMY_NODE_ID, 76 value: P(ast::Expr { 77 id: ast::DUMMY_NODE_ID, 78 kind, 79 span, 80 attrs: AttrVec::new(), 81 tokens: None, 82 }), 83 } 84 } 85 const_ident(&self, span: Span, ident: Ident) -> ast::AnonConst86 pub fn const_ident(&self, span: Span, ident: Ident) -> ast::AnonConst { 87 self.anon_const(span, ast::ExprKind::Path(None, self.path_ident(span, ident))) 88 } 89 ty_ref( &self, span: Span, ty: P<ast::Ty>, lifetime: Option<ast::Lifetime>, mutbl: ast::Mutability, ) -> P<ast::Ty>90 pub fn ty_ref( 91 &self, 92 span: Span, 93 ty: P<ast::Ty>, 94 lifetime: Option<ast::Lifetime>, 95 mutbl: ast::Mutability, 96 ) -> P<ast::Ty> { 97 self.ty(span, ast::TyKind::Ref(lifetime, self.ty_mt(ty, mutbl))) 98 } 99 ty_ptr(&self, span: Span, ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty>100 pub fn ty_ptr(&self, span: Span, ty: P<ast::Ty>, mutbl: ast::Mutability) -> P<ast::Ty> { 101 self.ty(span, ast::TyKind::Ptr(self.ty_mt(ty, mutbl))) 102 } 103 typaram( &self, span: Span, ident: Ident, bounds: ast::GenericBounds, default: Option<P<ast::Ty>>, ) -> ast::GenericParam104 pub fn typaram( 105 &self, 106 span: Span, 107 ident: Ident, 108 bounds: ast::GenericBounds, 109 default: Option<P<ast::Ty>>, 110 ) -> ast::GenericParam { 111 ast::GenericParam { 112 ident: ident.with_span_pos(span), 113 id: ast::DUMMY_NODE_ID, 114 attrs: AttrVec::new(), 115 bounds, 116 kind: ast::GenericParamKind::Type { default }, 117 is_placeholder: false, 118 colon_span: None, 119 } 120 } 121 trait_ref(&self, path: ast::Path) -> ast::TraitRef122 pub fn trait_ref(&self, path: ast::Path) -> ast::TraitRef { 123 ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID } 124 } 125 poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef126 pub fn poly_trait_ref(&self, span: Span, path: ast::Path) -> ast::PolyTraitRef { 127 ast::PolyTraitRef { 128 bound_generic_params: ThinVec::new(), 129 trait_ref: self.trait_ref(path), 130 span, 131 } 132 } 133 trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound134 pub fn trait_bound(&self, path: ast::Path, is_const: bool) -> ast::GenericBound { 135 ast::GenericBound::Trait( 136 self.poly_trait_ref(path.span, path), 137 if is_const { 138 ast::TraitBoundModifier::MaybeConst 139 } else { 140 ast::TraitBoundModifier::None 141 }, 142 ) 143 } 144 lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime145 pub fn lifetime(&self, span: Span, ident: Ident) -> ast::Lifetime { 146 ast::Lifetime { id: ast::DUMMY_NODE_ID, ident: ident.with_span_pos(span) } 147 } 148 lifetime_static(&self, span: Span) -> ast::Lifetime149 pub fn lifetime_static(&self, span: Span) -> ast::Lifetime { 150 self.lifetime(span, Ident::new(kw::StaticLifetime, span)) 151 } 152 stmt_expr(&self, expr: P<ast::Expr>) -> ast::Stmt153 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) } 155 } 156 stmt_let_pat(&self, sp: Span, pat: P<ast::Pat>, ex: P<ast::Expr>) -> ast::Stmt157 pub fn stmt_let_pat(&self, sp: Span, pat: P<ast::Pat>, ex: P<ast::Expr>) -> ast::Stmt { 158 let local = P(ast::Local { 159 pat, 160 ty: None, 161 id: ast::DUMMY_NODE_ID, 162 kind: LocalKind::Init(ex), 163 span: sp, 164 attrs: AttrVec::new(), 165 tokens: None, 166 }); 167 self.stmt_local(local, sp) 168 } 169 stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt170 pub fn stmt_let(&self, sp: Span, mutbl: bool, ident: Ident, ex: P<ast::Expr>) -> ast::Stmt { 171 self.stmt_let_ty(sp, mutbl, ident, None, ex) 172 } 173 stmt_let_ty( &self, sp: Span, mutbl: bool, ident: Ident, ty: Option<P<ast::Ty>>, ex: P<ast::Expr>, ) -> ast::Stmt174 pub fn stmt_let_ty( 175 &self, 176 sp: Span, 177 mutbl: bool, 178 ident: Ident, 179 ty: Option<P<ast::Ty>>, 180 ex: P<ast::Expr>, 181 ) -> ast::Stmt { 182 let pat = if mutbl { 183 self.pat_ident_binding_mode(sp, ident, ast::BindingAnnotation::MUT) 184 } else { 185 self.pat_ident(sp, ident) 186 }; 187 let local = P(ast::Local { 188 pat, 189 ty, 190 id: ast::DUMMY_NODE_ID, 191 kind: LocalKind::Init(ex), 192 span: sp, 193 attrs: AttrVec::new(), 194 tokens: None, 195 }); 196 self.stmt_local(local, sp) 197 } 198 199 /// Generates `let _: Type;`, which is usually used for type assertions. stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt200 pub fn stmt_let_type_only(&self, span: Span, ty: P<ast::Ty>) -> ast::Stmt { 201 let local = P(ast::Local { 202 pat: self.pat_wild(span), 203 ty: Some(ty), 204 id: ast::DUMMY_NODE_ID, 205 kind: LocalKind::Decl, 206 span, 207 attrs: AttrVec::new(), 208 tokens: None, 209 }); 210 self.stmt_local(local, span) 211 } 212 stmt_local(&self, local: P<ast::Local>, span: Span) -> ast::Stmt213 pub fn stmt_local(&self, local: P<ast::Local>, span: Span) -> ast::Stmt { 214 ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span } 215 } 216 stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt217 pub fn stmt_item(&self, sp: Span, item: P<ast::Item>) -> ast::Stmt { 218 ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Item(item), span: sp } 219 } 220 block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block>221 pub fn block_expr(&self, expr: P<ast::Expr>) -> P<ast::Block> { 222 self.block( 223 expr.span, 224 thin_vec![ast::Stmt { 225 id: ast::DUMMY_NODE_ID, 226 span: expr.span, 227 kind: ast::StmtKind::Expr(expr), 228 }], 229 ) 230 } block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> P<ast::Block>231 pub fn block(&self, span: Span, stmts: ThinVec<ast::Stmt>) -> P<ast::Block> { 232 P(ast::Block { 233 stmts, 234 id: ast::DUMMY_NODE_ID, 235 rules: BlockCheckMode::Default, 236 span, 237 tokens: None, 238 could_be_bare_literal: false, 239 }) 240 } 241 expr(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr>242 pub fn expr(&self, span: Span, kind: ast::ExprKind) -> P<ast::Expr> { 243 P(ast::Expr { id: ast::DUMMY_NODE_ID, kind, span, attrs: AttrVec::new(), tokens: None }) 244 } 245 expr_path(&self, path: ast::Path) -> P<ast::Expr>246 pub fn expr_path(&self, path: ast::Path) -> P<ast::Expr> { 247 self.expr(path.span, ast::ExprKind::Path(None, path)) 248 } 249 expr_ident(&self, span: Span, id: Ident) -> P<ast::Expr>250 pub fn expr_ident(&self, span: Span, id: Ident) -> P<ast::Expr> { 251 self.expr_path(self.path_ident(span, id)) 252 } expr_self(&self, span: Span) -> P<ast::Expr>253 pub fn expr_self(&self, span: Span) -> P<ast::Expr> { 254 self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower)) 255 } 256 expr_field(&self, span: Span, expr: P<Expr>, field: Ident) -> P<ast::Expr>257 pub fn expr_field(&self, span: Span, expr: P<Expr>, field: Ident) -> P<ast::Expr> { 258 self.expr(span, ast::ExprKind::Field(expr, field)) 259 } 260 expr_binary( &self, sp: Span, op: ast::BinOpKind, lhs: P<ast::Expr>, rhs: P<ast::Expr>, ) -> P<ast::Expr>261 pub fn expr_binary( 262 &self, 263 sp: Span, 264 op: ast::BinOpKind, 265 lhs: P<ast::Expr>, 266 rhs: P<ast::Expr>, 267 ) -> P<ast::Expr> { 268 self.expr(sp, ast::ExprKind::Binary(Spanned { node: op, span: sp }, lhs, rhs)) 269 } 270 expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>271 pub fn expr_deref(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> { 272 self.expr(sp, ast::ExprKind::Unary(UnOp::Deref, e)) 273 } 274 expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>275 pub fn expr_addr_of(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> { 276 self.expr(sp, ast::ExprKind::AddrOf(ast::BorrowKind::Ref, ast::Mutability::Not, e)) 277 } 278 expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr>279 pub fn expr_paren(&self, sp: Span, e: P<ast::Expr>) -> P<ast::Expr> { 280 self.expr(sp, ast::ExprKind::Paren(e)) 281 } 282 expr_call( &self, span: Span, expr: P<ast::Expr>, args: ThinVec<P<ast::Expr>>, ) -> P<ast::Expr>283 pub fn expr_call( 284 &self, 285 span: Span, 286 expr: P<ast::Expr>, 287 args: ThinVec<P<ast::Expr>>, 288 ) -> P<ast::Expr> { 289 self.expr(span, ast::ExprKind::Call(expr, args)) 290 } expr_call_ident( &self, span: Span, id: Ident, args: ThinVec<P<ast::Expr>>, ) -> P<ast::Expr>291 pub fn expr_call_ident( 292 &self, 293 span: Span, 294 id: Ident, 295 args: ThinVec<P<ast::Expr>>, 296 ) -> P<ast::Expr> { 297 self.expr(span, ast::ExprKind::Call(self.expr_ident(span, id), args)) 298 } expr_call_global( &self, sp: Span, fn_path: Vec<Ident>, args: ThinVec<P<ast::Expr>>, ) -> P<ast::Expr>299 pub fn expr_call_global( 300 &self, 301 sp: Span, 302 fn_path: Vec<Ident>, 303 args: ThinVec<P<ast::Expr>>, 304 ) -> P<ast::Expr> { 305 let pathexpr = self.expr_path(self.path_global(sp, fn_path)); 306 self.expr_call(sp, pathexpr, args) 307 } expr_block(&self, b: P<ast::Block>) -> P<ast::Expr>308 pub fn expr_block(&self, b: P<ast::Block>) -> P<ast::Expr> { 309 self.expr(b.span, ast::ExprKind::Block(b, None)) 310 } field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::ExprField311 pub fn field_imm(&self, span: Span, ident: Ident, e: P<ast::Expr>) -> ast::ExprField { 312 ast::ExprField { 313 ident: ident.with_span_pos(span), 314 expr: e, 315 span, 316 is_shorthand: false, 317 attrs: AttrVec::new(), 318 id: ast::DUMMY_NODE_ID, 319 is_placeholder: false, 320 } 321 } expr_struct( &self, span: Span, path: ast::Path, fields: ThinVec<ast::ExprField>, ) -> P<ast::Expr>322 pub fn expr_struct( 323 &self, 324 span: Span, 325 path: ast::Path, 326 fields: ThinVec<ast::ExprField>, 327 ) -> P<ast::Expr> { 328 self.expr( 329 span, 330 ast::ExprKind::Struct(P(ast::StructExpr { 331 qself: None, 332 path, 333 fields, 334 rest: ast::StructRest::None, 335 })), 336 ) 337 } expr_struct_ident( &self, span: Span, id: Ident, fields: ThinVec<ast::ExprField>, ) -> P<ast::Expr>338 pub fn expr_struct_ident( 339 &self, 340 span: Span, 341 id: Ident, 342 fields: ThinVec<ast::ExprField>, 343 ) -> P<ast::Expr> { 344 self.expr_struct(span, self.path_ident(span, id), fields) 345 } 346 expr_usize(&self, span: Span, n: usize) -> P<ast::Expr>347 pub fn expr_usize(&self, span: Span, n: usize) -> P<ast::Expr> { 348 let suffix = Some(ast::UintTy::Usize.name()); 349 let lit = token::Lit::new(token::Integer, sym::integer(n), suffix); 350 self.expr(span, ast::ExprKind::Lit(lit)) 351 } 352 expr_u32(&self, span: Span, n: u32) -> P<ast::Expr>353 pub fn expr_u32(&self, span: Span, n: u32) -> P<ast::Expr> { 354 let suffix = Some(ast::UintTy::U32.name()); 355 let lit = token::Lit::new(token::Integer, sym::integer(n), suffix); 356 self.expr(span, ast::ExprKind::Lit(lit)) 357 } 358 expr_bool(&self, span: Span, value: bool) -> P<ast::Expr>359 pub fn expr_bool(&self, span: Span, value: bool) -> P<ast::Expr> { 360 let lit = token::Lit::new(token::Bool, if value { kw::True } else { kw::False }, None); 361 self.expr(span, ast::ExprKind::Lit(lit)) 362 } 363 expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr>364 pub fn expr_str(&self, span: Span, s: Symbol) -> P<ast::Expr> { 365 let lit = token::Lit::new(token::Str, literal::escape_string_symbol(s), None); 366 self.expr(span, ast::ExprKind::Lit(lit)) 367 } 368 expr_char(&self, span: Span, ch: char) -> P<ast::Expr>369 pub fn expr_char(&self, span: Span, ch: char) -> P<ast::Expr> { 370 let lit = token::Lit::new(token::Char, literal::escape_char_symbol(ch), None); 371 self.expr(span, ast::ExprKind::Lit(lit)) 372 } 373 expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr>374 pub fn expr_byte_str(&self, span: Span, bytes: Vec<u8>) -> P<ast::Expr> { 375 let lit = token::Lit::new(token::ByteStr, literal::escape_byte_str_symbol(&bytes), None); 376 self.expr(span, ast::ExprKind::Lit(lit)) 377 } 378 379 /// `[expr1, expr2, ...]` expr_array(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr>380 pub fn expr_array(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> { 381 self.expr(sp, ast::ExprKind::Array(exprs)) 382 } 383 384 /// `&[expr1, expr2, ...]` expr_array_ref(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr>385 pub fn expr_array_ref(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> { 386 self.expr_addr_of(sp, self.expr_array(sp, exprs)) 387 } 388 expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr>389 pub fn expr_cast(&self, sp: Span, expr: P<ast::Expr>, ty: P<ast::Ty>) -> P<ast::Expr> { 390 self.expr(sp, ast::ExprKind::Cast(expr, ty)) 391 } 392 expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr>393 pub fn expr_some(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> { 394 let some = self.std_path(&[sym::option, sym::Option, sym::Some]); 395 self.expr_call_global(sp, some, thin_vec![expr]) 396 } 397 expr_none(&self, sp: Span) -> P<ast::Expr>398 pub fn expr_none(&self, sp: Span) -> P<ast::Expr> { 399 let none = self.std_path(&[sym::option, sym::Option, sym::None]); 400 self.expr_path(self.path_global(sp, none)) 401 } expr_tuple(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr>402 pub fn expr_tuple(&self, sp: Span, exprs: ThinVec<P<ast::Expr>>) -> P<ast::Expr> { 403 self.expr(sp, ast::ExprKind::Tup(exprs)) 404 } 405 expr_fail(&self, span: Span, msg: Symbol) -> P<ast::Expr>406 pub fn expr_fail(&self, span: Span, msg: Symbol) -> P<ast::Expr> { 407 self.expr_call_global( 408 span, 409 [sym::std, sym::rt, sym::begin_panic].iter().map(|s| Ident::new(*s, span)).collect(), 410 thin_vec![self.expr_str(span, msg)], 411 ) 412 } 413 expr_unreachable(&self, span: Span) -> P<ast::Expr>414 pub fn expr_unreachable(&self, span: Span) -> P<ast::Expr> { 415 self.expr_fail(span, Symbol::intern("internal error: entered unreachable code")) 416 } 417 expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr>418 pub fn expr_ok(&self, sp: Span, expr: P<ast::Expr>) -> P<ast::Expr> { 419 let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]); 420 self.expr_call_global(sp, ok, thin_vec![expr]) 421 } 422 expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr>423 pub fn expr_try(&self, sp: Span, head: P<ast::Expr>) -> P<ast::Expr> { 424 let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]); 425 let ok_path = self.path_global(sp, ok); 426 let err = self.std_path(&[sym::result, sym::Result, sym::Err]); 427 let err_path = self.path_global(sp, err); 428 429 let binding_variable = Ident::new(sym::__try_var, sp); 430 let binding_pat = self.pat_ident(sp, binding_variable); 431 let binding_expr = self.expr_ident(sp, binding_variable); 432 433 // `Ok(__try_var)` pattern 434 let ok_pat = self.pat_tuple_struct(sp, ok_path, thin_vec![binding_pat.clone()]); 435 436 // `Err(__try_var)` (pattern and expression respectively) 437 let err_pat = self.pat_tuple_struct(sp, err_path.clone(), thin_vec![binding_pat]); 438 let err_inner_expr = 439 self.expr_call(sp, self.expr_path(err_path), thin_vec![binding_expr.clone()]); 440 // `return Err(__try_var)` 441 let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr))); 442 443 // `Ok(__try_var) => __try_var` 444 let ok_arm = self.arm(sp, ok_pat, binding_expr); 445 // `Err(__try_var) => return Err(__try_var)` 446 let err_arm = self.arm(sp, err_pat, err_expr); 447 448 // `match head { Ok() => ..., Err() => ... }` 449 self.expr_match(sp, head, thin_vec![ok_arm, err_arm]) 450 } 451 pat(&self, span: Span, kind: PatKind) -> P<ast::Pat>452 pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> { 453 P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None }) 454 } pat_wild(&self, span: Span) -> P<ast::Pat>455 pub fn pat_wild(&self, span: Span) -> P<ast::Pat> { 456 self.pat(span, PatKind::Wild) 457 } pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat>458 pub fn pat_lit(&self, span: Span, expr: P<ast::Expr>) -> P<ast::Pat> { 459 self.pat(span, PatKind::Lit(expr)) 460 } pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat>461 pub fn pat_ident(&self, span: Span, ident: Ident) -> P<ast::Pat> { 462 self.pat_ident_binding_mode(span, ident, ast::BindingAnnotation::NONE) 463 } 464 pat_ident_binding_mode( &self, span: Span, ident: Ident, ann: ast::BindingAnnotation, ) -> P<ast::Pat>465 pub fn pat_ident_binding_mode( 466 &self, 467 span: Span, 468 ident: Ident, 469 ann: ast::BindingAnnotation, 470 ) -> P<ast::Pat> { 471 let pat = PatKind::Ident(ann, ident.with_span_pos(span), None); 472 self.pat(span, pat) 473 } pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat>474 pub fn pat_path(&self, span: Span, path: ast::Path) -> P<ast::Pat> { 475 self.pat(span, PatKind::Path(None, path)) 476 } pat_tuple_struct( &self, span: Span, path: ast::Path, subpats: ThinVec<P<ast::Pat>>, ) -> P<ast::Pat>477 pub fn pat_tuple_struct( 478 &self, 479 span: Span, 480 path: ast::Path, 481 subpats: ThinVec<P<ast::Pat>>, 482 ) -> P<ast::Pat> { 483 self.pat(span, PatKind::TupleStruct(None, path, subpats)) 484 } pat_struct( &self, span: Span, path: ast::Path, field_pats: ThinVec<ast::PatField>, ) -> P<ast::Pat>485 pub fn pat_struct( 486 &self, 487 span: Span, 488 path: ast::Path, 489 field_pats: ThinVec<ast::PatField>, 490 ) -> P<ast::Pat> { 491 self.pat(span, PatKind::Struct(None, path, field_pats, false)) 492 } pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat>493 pub fn pat_tuple(&self, span: Span, pats: ThinVec<P<ast::Pat>>) -> P<ast::Pat> { 494 self.pat(span, PatKind::Tuple(pats)) 495 } 496 pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat>497 pub fn pat_some(&self, span: Span, pat: P<ast::Pat>) -> P<ast::Pat> { 498 let some = self.std_path(&[sym::option, sym::Option, sym::Some]); 499 let path = self.path_global(span, some); 500 self.pat_tuple_struct(span, path, thin_vec![pat]) 501 } 502 arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm503 pub fn arm(&self, span: Span, pat: P<ast::Pat>, expr: P<ast::Expr>) -> ast::Arm { 504 ast::Arm { 505 attrs: AttrVec::new(), 506 pat, 507 guard: None, 508 body: expr, 509 span, 510 id: ast::DUMMY_NODE_ID, 511 is_placeholder: false, 512 } 513 } 514 arm_unreachable(&self, span: Span) -> ast::Arm515 pub fn arm_unreachable(&self, span: Span) -> ast::Arm { 516 self.arm(span, self.pat_wild(span), self.expr_unreachable(span)) 517 } 518 expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr>519 pub fn expr_match(&self, span: Span, arg: P<ast::Expr>, arms: ThinVec<ast::Arm>) -> P<Expr> { 520 self.expr(span, ast::ExprKind::Match(arg, arms)) 521 } 522 expr_if( &self, span: Span, cond: P<ast::Expr>, then: P<ast::Expr>, els: Option<P<ast::Expr>>, ) -> P<ast::Expr>523 pub fn expr_if( 524 &self, 525 span: Span, 526 cond: P<ast::Expr>, 527 then: P<ast::Expr>, 528 els: Option<P<ast::Expr>>, 529 ) -> P<ast::Expr> { 530 let els = els.map(|x| self.expr_block(self.block_expr(x))); 531 self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els)) 532 } 533 lambda(&self, span: Span, ids: Vec<Ident>, body: P<ast::Expr>) -> P<ast::Expr>534 pub fn lambda(&self, span: Span, ids: Vec<Ident>, body: P<ast::Expr>) -> P<ast::Expr> { 535 let fn_decl = self.fn_decl( 536 ids.iter().map(|id| self.param(span, *id, self.ty(span, ast::TyKind::Infer))).collect(), 537 ast::FnRetTy::Default(span), 538 ); 539 540 // FIXME -- We are using `span` as the span of the `|...|` 541 // part of the lambda, but it probably (maybe?) corresponds to 542 // the entire lambda body. Probably we should extend the API 543 // here, but that's not entirely clear. 544 self.expr( 545 span, 546 ast::ExprKind::Closure(Box::new(ast::Closure { 547 binder: ast::ClosureBinder::NotPresent, 548 capture_clause: ast::CaptureBy::Ref, 549 constness: ast::Const::No, 550 asyncness: ast::Async::No, 551 movability: ast::Movability::Movable, 552 fn_decl, 553 body, 554 fn_decl_span: span, 555 // FIXME(SarthakSingh31): This points to the start of the declaration block and 556 // not the span of the argument block. 557 fn_arg_span: span, 558 })), 559 ) 560 } 561 lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr>562 pub fn lambda0(&self, span: Span, body: P<ast::Expr>) -> P<ast::Expr> { 563 self.lambda(span, Vec::new(), body) 564 } 565 lambda1(&self, span: Span, body: P<ast::Expr>, ident: Ident) -> P<ast::Expr>566 pub fn lambda1(&self, span: Span, body: P<ast::Expr>, ident: Ident) -> P<ast::Expr> { 567 self.lambda(span, vec![ident], body) 568 } 569 lambda_stmts_1( &self, span: Span, stmts: ThinVec<ast::Stmt>, ident: Ident, ) -> P<ast::Expr>570 pub fn lambda_stmts_1( 571 &self, 572 span: Span, 573 stmts: ThinVec<ast::Stmt>, 574 ident: Ident, 575 ) -> P<ast::Expr> { 576 self.lambda1(span, self.expr_block(self.block(span, stmts)), ident) 577 } 578 param(&self, span: Span, ident: Ident, ty: P<ast::Ty>) -> ast::Param579 pub fn param(&self, span: Span, ident: Ident, ty: P<ast::Ty>) -> ast::Param { 580 let arg_pat = self.pat_ident(span, ident); 581 ast::Param { 582 attrs: AttrVec::default(), 583 id: ast::DUMMY_NODE_ID, 584 pat: arg_pat, 585 span, 586 ty, 587 is_placeholder: false, 588 } 589 } 590 591 // `self` is unused but keep it as method for the convenience use. fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl>592 pub fn fn_decl(&self, inputs: ThinVec<ast::Param>, output: ast::FnRetTy) -> P<ast::FnDecl> { 593 P(ast::FnDecl { inputs, output }) 594 } 595 item( &self, span: Span, name: Ident, attrs: ast::AttrVec, kind: ast::ItemKind, ) -> P<ast::Item>596 pub fn item( 597 &self, 598 span: Span, 599 name: Ident, 600 attrs: ast::AttrVec, 601 kind: ast::ItemKind, 602 ) -> P<ast::Item> { 603 P(ast::Item { 604 ident: name, 605 attrs, 606 id: ast::DUMMY_NODE_ID, 607 kind, 608 vis: ast::Visibility { 609 span: span.shrink_to_lo(), 610 kind: ast::VisibilityKind::Inherited, 611 tokens: None, 612 }, 613 span, 614 tokens: None, 615 }) 616 } 617 item_static( &self, span: Span, name: Ident, ty: P<ast::Ty>, mutability: ast::Mutability, expr: P<ast::Expr>, ) -> P<ast::Item>618 pub fn item_static( 619 &self, 620 span: Span, 621 name: Ident, 622 ty: P<ast::Ty>, 623 mutability: ast::Mutability, 624 expr: P<ast::Expr>, 625 ) -> P<ast::Item> { 626 self.item( 627 span, 628 name, 629 AttrVec::new(), 630 ast::ItemKind::Static(ast::StaticItem { ty, mutability, expr: Some(expr) }.into()), 631 ) 632 } 633 item_const( &self, span: Span, name: Ident, ty: P<ast::Ty>, expr: P<ast::Expr>, ) -> P<ast::Item>634 pub fn item_const( 635 &self, 636 span: Span, 637 name: Ident, 638 ty: P<ast::Ty>, 639 expr: P<ast::Expr>, 640 ) -> P<ast::Item> { 641 let defaultness = ast::Defaultness::Final; 642 self.item( 643 span, 644 name, 645 AttrVec::new(), 646 ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr: Some(expr) }.into()), 647 ) 648 } 649 650 // Builds `#[name]`. attr_word(&self, name: Symbol, span: Span) -> ast::Attribute651 pub fn attr_word(&self, name: Symbol, span: Span) -> ast::Attribute { 652 let g = &self.sess.parse_sess.attr_id_generator; 653 attr::mk_attr_word(g, ast::AttrStyle::Outer, name, span) 654 } 655 656 // Builds `#[name = val]`. 657 // 658 // Note: `span` is used for both the identifier and the value. attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute659 pub fn attr_name_value_str(&self, name: Symbol, val: Symbol, span: Span) -> ast::Attribute { 660 let g = &self.sess.parse_sess.attr_id_generator; 661 attr::mk_attr_name_value_str(g, ast::AttrStyle::Outer, name, val, span) 662 } 663 664 // Builds `#[outer(inner)]`. attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute665 pub fn attr_nested_word(&self, outer: Symbol, inner: Symbol, span: Span) -> ast::Attribute { 666 let g = &self.sess.parse_sess.attr_id_generator; 667 attr::mk_attr_nested_word(g, ast::AttrStyle::Outer, outer, inner, span) 668 } 669 } 670