1 use super::errors::{ 2 AsyncGeneratorsNotSupported, AsyncNonMoveClosureNotSupported, AwaitOnlyInAsyncFnAndBlocks, 3 BaseExpressionDoubleDot, ClosureCannotBeStatic, FunctionalRecordUpdateDestructuringAssignment, 4 GeneratorTooManyParameters, InclusiveRangeWithNoEnd, NotSupportedForLifetimeBinderAsyncClosure, 5 UnderscoreExprLhsAssign, 6 }; 7 use super::ResolverAstLoweringExt; 8 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs}; 9 use crate::{FnDeclKind, ImplTraitPosition}; 10 use rustc_ast::attr; 11 use rustc_ast::ptr::P as AstP; 12 use rustc_ast::*; 13 use rustc_data_structures::stack::ensure_sufficient_stack; 14 use rustc_hir as hir; 15 use rustc_hir::def::Res; 16 use rustc_hir::definitions::DefPathData; 17 use rustc_session::errors::report_lit_error; 18 use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned}; 19 use rustc_span::symbol::{sym, Ident, Symbol}; 20 use rustc_span::DUMMY_SP; 21 use thin_vec::{thin_vec, ThinVec}; 22 23 impl<'hir> LoweringContext<'_, 'hir> { lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>]24 fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] { 25 self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x))) 26 } 27 lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir>28 pub(super) fn lower_expr(&mut self, e: &Expr) -> &'hir hir::Expr<'hir> { 29 self.arena.alloc(self.lower_expr_mut(e)) 30 } 31 lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir>32 pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> { 33 ensure_sufficient_stack(|| { 34 match &e.kind { 35 // Parenthesis expression does not have a HirId and is handled specially. 36 ExprKind::Paren(ex) => { 37 let mut ex = self.lower_expr_mut(ex); 38 // Include parens in span, but only if it is a super-span. 39 if e.span.contains(ex.span) { 40 ex.span = self.lower_span(e.span); 41 } 42 // Merge attributes into the inner expression. 43 if !e.attrs.is_empty() { 44 let old_attrs = 45 self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]); 46 self.attrs.insert( 47 ex.hir_id.local_id, 48 &*self.arena.alloc_from_iter( 49 e.attrs 50 .iter() 51 .map(|a| self.lower_attr(a)) 52 .chain(old_attrs.iter().cloned()), 53 ), 54 ); 55 } 56 return ex; 57 } 58 // Desugar `ExprForLoop` 59 // from: `[opt_ident]: for <pat> in <head> <body>` 60 // 61 // This also needs special handling because the HirId of the returned `hir::Expr` will not 62 // correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself. 63 ExprKind::ForLoop(pat, head, body, opt_label) => { 64 return self.lower_expr_for(e, pat, head, body, *opt_label); 65 } 66 _ => (), 67 } 68 69 let hir_id = self.lower_node_id(e.id); 70 self.lower_attrs(hir_id, &e.attrs); 71 72 let kind = match &e.kind { 73 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)), 74 ExprKind::ConstBlock(c) => { 75 let c = self.with_new_scopes(|this| hir::ConstBlock { 76 def_id: this.local_def_id(c.id), 77 hir_id: this.lower_node_id(c.id), 78 body: this.lower_const_body(c.value.span, Some(&c.value)), 79 }); 80 hir::ExprKind::ConstBlock(c) 81 } 82 ExprKind::Repeat(expr, count) => { 83 let expr = self.lower_expr(expr); 84 let count = self.lower_array_length(count); 85 hir::ExprKind::Repeat(expr, count) 86 } 87 ExprKind::Tup(elts) => hir::ExprKind::Tup(self.lower_exprs(elts)), 88 ExprKind::Call(f, args) => { 89 if let Some(legacy_args) = self.resolver.legacy_const_generic_args(f) { 90 self.lower_legacy_const_generics((**f).clone(), args.clone(), &legacy_args) 91 } else { 92 let f = self.lower_expr(f); 93 hir::ExprKind::Call(f, self.lower_exprs(args)) 94 } 95 } 96 ExprKind::MethodCall(box MethodCall { seg, receiver, args, span }) => { 97 let hir_seg = self.arena.alloc(self.lower_path_segment( 98 e.span, 99 seg, 100 ParamMode::Optional, 101 ParenthesizedGenericArgs::Err, 102 &ImplTraitContext::Disallowed(ImplTraitPosition::Path), 103 )); 104 let receiver = self.lower_expr(receiver); 105 let args = 106 self.arena.alloc_from_iter(args.iter().map(|x| self.lower_expr_mut(x))); 107 hir::ExprKind::MethodCall(hir_seg, receiver, args, self.lower_span(*span)) 108 } 109 ExprKind::Binary(binop, lhs, rhs) => { 110 let binop = self.lower_binop(*binop); 111 let lhs = self.lower_expr(lhs); 112 let rhs = self.lower_expr(rhs); 113 hir::ExprKind::Binary(binop, lhs, rhs) 114 } 115 ExprKind::Unary(op, ohs) => { 116 let op = self.lower_unop(*op); 117 let ohs = self.lower_expr(ohs); 118 hir::ExprKind::Unary(op, ohs) 119 } 120 ExprKind::Lit(token_lit) => { 121 let lit_kind = match LitKind::from_token_lit(*token_lit) { 122 Ok(lit_kind) => lit_kind, 123 Err(err) => { 124 report_lit_error(&self.tcx.sess.parse_sess, err, *token_lit, e.span); 125 LitKind::Err 126 } 127 }; 128 let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind)); 129 hir::ExprKind::Lit(lit) 130 } 131 ExprKind::IncludedBytes(bytes) => { 132 let lit = self.arena.alloc(respan( 133 self.lower_span(e.span), 134 LitKind::ByteStr(bytes.clone(), StrStyle::Cooked), 135 )); 136 hir::ExprKind::Lit(lit) 137 } 138 ExprKind::Cast(expr, ty) => { 139 let expr = self.lower_expr(expr); 140 let ty = 141 self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); 142 hir::ExprKind::Cast(expr, ty) 143 } 144 ExprKind::Type(expr, ty) => { 145 let expr = self.lower_expr(expr); 146 let ty = 147 self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::Cast)); 148 hir::ExprKind::Type(expr, ty) 149 } 150 ExprKind::AddrOf(k, m, ohs) => { 151 let ohs = self.lower_expr(ohs); 152 hir::ExprKind::AddrOf(*k, *m, ohs) 153 } 154 ExprKind::Let(pat, scrutinee, span) => { 155 hir::ExprKind::Let(self.arena.alloc(hir::Let { 156 hir_id: self.next_id(), 157 span: self.lower_span(*span), 158 pat: self.lower_pat(pat), 159 ty: None, 160 init: self.lower_expr(scrutinee), 161 })) 162 } 163 ExprKind::If(cond, then, else_opt) => { 164 self.lower_expr_if(cond, then, else_opt.as_deref()) 165 } 166 ExprKind::While(cond, body, opt_label) => self.with_loop_scope(e.id, |this| { 167 let span = this.mark_span_with_reason(DesugaringKind::WhileLoop, e.span, None); 168 this.lower_expr_while_in_loop_scope(span, cond, body, *opt_label) 169 }), 170 ExprKind::Loop(body, opt_label, span) => self.with_loop_scope(e.id, |this| { 171 hir::ExprKind::Loop( 172 this.lower_block(body, false), 173 this.lower_label(*opt_label), 174 hir::LoopSource::Loop, 175 this.lower_span(*span), 176 ) 177 }), 178 ExprKind::TryBlock(body) => self.lower_expr_try_block(body), 179 ExprKind::Match(expr, arms) => hir::ExprKind::Match( 180 self.lower_expr(expr), 181 self.arena.alloc_from_iter(arms.iter().map(|x| self.lower_arm(x))), 182 hir::MatchSource::Normal, 183 ), 184 ExprKind::Async(capture_clause, block) => self.make_async_expr( 185 *capture_clause, 186 e.id, 187 None, 188 e.span, 189 hir::AsyncGeneratorKind::Block, 190 |this| this.with_new_scopes(|this| this.lower_block_expr(block)), 191 ), 192 ExprKind::Await(expr, await_kw_span) => self.lower_expr_await(*await_kw_span, expr), 193 ExprKind::Closure(box Closure { 194 binder, 195 capture_clause, 196 constness, 197 asyncness, 198 movability, 199 fn_decl, 200 body, 201 fn_decl_span, 202 fn_arg_span, 203 }) => { 204 if let Async::Yes { closure_id, .. } = asyncness { 205 self.lower_expr_async_closure( 206 binder, 207 *capture_clause, 208 e.id, 209 hir_id, 210 *closure_id, 211 fn_decl, 212 body, 213 *fn_decl_span, 214 *fn_arg_span, 215 ) 216 } else { 217 self.lower_expr_closure( 218 binder, 219 *capture_clause, 220 e.id, 221 *constness, 222 *movability, 223 fn_decl, 224 body, 225 *fn_decl_span, 226 *fn_arg_span, 227 ) 228 } 229 } 230 ExprKind::Block(blk, opt_label) => { 231 let opt_label = self.lower_label(*opt_label); 232 hir::ExprKind::Block(self.lower_block(blk, opt_label.is_some()), opt_label) 233 } 234 ExprKind::Assign(el, er, span) => self.lower_expr_assign(el, er, *span, e.span), 235 ExprKind::AssignOp(op, el, er) => hir::ExprKind::AssignOp( 236 self.lower_binop(*op), 237 self.lower_expr(el), 238 self.lower_expr(er), 239 ), 240 ExprKind::Field(el, ident) => { 241 hir::ExprKind::Field(self.lower_expr(el), self.lower_ident(*ident)) 242 } 243 ExprKind::Index(el, er) => { 244 hir::ExprKind::Index(self.lower_expr(el), self.lower_expr(er)) 245 } 246 ExprKind::Range(Some(e1), Some(e2), RangeLimits::Closed) => { 247 self.lower_expr_range_closed(e.span, e1, e2) 248 } 249 ExprKind::Range(e1, e2, lims) => { 250 self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), *lims) 251 } 252 ExprKind::Underscore => { 253 let guar = self.tcx.sess.emit_err(UnderscoreExprLhsAssign { span: e.span }); 254 hir::ExprKind::Err(guar) 255 } 256 ExprKind::Path(qself, path) => { 257 let qpath = self.lower_qpath( 258 e.id, 259 qself, 260 path, 261 ParamMode::Optional, 262 &ImplTraitContext::Disallowed(ImplTraitPosition::Path), 263 ); 264 hir::ExprKind::Path(qpath) 265 } 266 ExprKind::Break(opt_label, opt_expr) => { 267 let opt_expr = opt_expr.as_ref().map(|x| self.lower_expr(x)); 268 hir::ExprKind::Break(self.lower_jump_destination(e.id, *opt_label), opt_expr) 269 } 270 ExprKind::Continue(opt_label) => { 271 hir::ExprKind::Continue(self.lower_jump_destination(e.id, *opt_label)) 272 } 273 ExprKind::Ret(e) => { 274 let e = e.as_ref().map(|x| self.lower_expr(x)); 275 hir::ExprKind::Ret(e) 276 } 277 ExprKind::Yeet(sub_expr) => self.lower_expr_yeet(e.span, sub_expr.as_deref()), 278 ExprKind::Become(sub_expr) => { 279 let sub_expr = self.lower_expr(sub_expr); 280 hir::ExprKind::Become(sub_expr) 281 } 282 ExprKind::InlineAsm(asm) => { 283 hir::ExprKind::InlineAsm(self.lower_inline_asm(e.span, asm)) 284 } 285 ExprKind::FormatArgs(fmt) => self.lower_format_args(e.span, fmt), 286 ExprKind::OffsetOf(container, fields) => hir::ExprKind::OffsetOf( 287 self.lower_ty( 288 container, 289 &mut ImplTraitContext::Disallowed(ImplTraitPosition::OffsetOf), 290 ), 291 self.arena.alloc_from_iter(fields.iter().map(|&ident| self.lower_ident(ident))), 292 ), 293 ExprKind::Struct(se) => { 294 let rest = match &se.rest { 295 StructRest::Base(e) => Some(self.lower_expr(e)), 296 StructRest::Rest(sp) => { 297 let guar = 298 self.tcx.sess.emit_err(BaseExpressionDoubleDot { span: *sp }); 299 Some(&*self.arena.alloc(self.expr_err(*sp, guar))) 300 } 301 StructRest::None => None, 302 }; 303 hir::ExprKind::Struct( 304 self.arena.alloc(self.lower_qpath( 305 e.id, 306 &se.qself, 307 &se.path, 308 ParamMode::Optional, 309 &ImplTraitContext::Disallowed(ImplTraitPosition::Path), 310 )), 311 self.arena 312 .alloc_from_iter(se.fields.iter().map(|x| self.lower_expr_field(x))), 313 rest, 314 ) 315 } 316 ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()), 317 ExprKind::Err => hir::ExprKind::Err( 318 self.tcx.sess.delay_span_bug(e.span, "lowered ExprKind::Err"), 319 ), 320 ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr), 321 322 ExprKind::Paren(_) | ExprKind::ForLoop(..) => { 323 unreachable!("already handled") 324 } 325 326 ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span), 327 }; 328 329 hir::Expr { hir_id, kind, span: self.lower_span(e.span) } 330 }) 331 } 332 lower_unop(&mut self, u: UnOp) -> hir::UnOp333 fn lower_unop(&mut self, u: UnOp) -> hir::UnOp { 334 match u { 335 UnOp::Deref => hir::UnOp::Deref, 336 UnOp::Not => hir::UnOp::Not, 337 UnOp::Neg => hir::UnOp::Neg, 338 } 339 } 340 lower_binop(&mut self, b: BinOp) -> hir::BinOp341 fn lower_binop(&mut self, b: BinOp) -> hir::BinOp { 342 Spanned { 343 node: match b.node { 344 BinOpKind::Add => hir::BinOpKind::Add, 345 BinOpKind::Sub => hir::BinOpKind::Sub, 346 BinOpKind::Mul => hir::BinOpKind::Mul, 347 BinOpKind::Div => hir::BinOpKind::Div, 348 BinOpKind::Rem => hir::BinOpKind::Rem, 349 BinOpKind::And => hir::BinOpKind::And, 350 BinOpKind::Or => hir::BinOpKind::Or, 351 BinOpKind::BitXor => hir::BinOpKind::BitXor, 352 BinOpKind::BitAnd => hir::BinOpKind::BitAnd, 353 BinOpKind::BitOr => hir::BinOpKind::BitOr, 354 BinOpKind::Shl => hir::BinOpKind::Shl, 355 BinOpKind::Shr => hir::BinOpKind::Shr, 356 BinOpKind::Eq => hir::BinOpKind::Eq, 357 BinOpKind::Lt => hir::BinOpKind::Lt, 358 BinOpKind::Le => hir::BinOpKind::Le, 359 BinOpKind::Ne => hir::BinOpKind::Ne, 360 BinOpKind::Ge => hir::BinOpKind::Ge, 361 BinOpKind::Gt => hir::BinOpKind::Gt, 362 }, 363 span: self.lower_span(b.span), 364 } 365 } 366 lower_legacy_const_generics( &mut self, mut f: Expr, args: ThinVec<AstP<Expr>>, legacy_args_idx: &[usize], ) -> hir::ExprKind<'hir>367 fn lower_legacy_const_generics( 368 &mut self, 369 mut f: Expr, 370 args: ThinVec<AstP<Expr>>, 371 legacy_args_idx: &[usize], 372 ) -> hir::ExprKind<'hir> { 373 let ExprKind::Path(None, path) = &mut f.kind else { 374 unreachable!(); 375 }; 376 377 // Split the arguments into const generics and normal arguments 378 let mut real_args = vec![]; 379 let mut generic_args = ThinVec::new(); 380 for (idx, arg) in args.into_iter().enumerate() { 381 if legacy_args_idx.contains(&idx) { 382 let parent_def_id = self.current_hir_id_owner; 383 let node_id = self.next_node_id(); 384 385 // Add a definition for the in-band const def. 386 self.create_def(parent_def_id.def_id, node_id, DefPathData::AnonConst, f.span); 387 388 let anon_const = AnonConst { id: node_id, value: arg }; 389 generic_args.push(AngleBracketedArg::Arg(GenericArg::Const(anon_const))); 390 } else { 391 real_args.push(arg); 392 } 393 } 394 395 // Add generic args to the last element of the path. 396 let last_segment = path.segments.last_mut().unwrap(); 397 assert!(last_segment.args.is_none()); 398 last_segment.args = Some(AstP(GenericArgs::AngleBracketed(AngleBracketedArgs { 399 span: DUMMY_SP, 400 args: generic_args, 401 }))); 402 403 // Now lower everything as normal. 404 let f = self.lower_expr(&f); 405 hir::ExprKind::Call(f, self.lower_exprs(&real_args)) 406 } 407 lower_expr_if( &mut self, cond: &Expr, then: &Block, else_opt: Option<&Expr>, ) -> hir::ExprKind<'hir>408 fn lower_expr_if( 409 &mut self, 410 cond: &Expr, 411 then: &Block, 412 else_opt: Option<&Expr>, 413 ) -> hir::ExprKind<'hir> { 414 let lowered_cond = self.lower_cond(cond); 415 let then_expr = self.lower_block_expr(then); 416 if let Some(rslt) = else_opt { 417 hir::ExprKind::If( 418 lowered_cond, 419 self.arena.alloc(then_expr), 420 Some(self.lower_expr(rslt)), 421 ) 422 } else { 423 hir::ExprKind::If(lowered_cond, self.arena.alloc(then_expr), None) 424 } 425 } 426 427 // Lowers a condition (i.e. `cond` in `if cond` or `while cond`), wrapping it in a terminating scope 428 // so that temporaries created in the condition don't live beyond it. lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir>429 fn lower_cond(&mut self, cond: &Expr) -> &'hir hir::Expr<'hir> { 430 fn has_let_expr(expr: &Expr) -> bool { 431 match &expr.kind { 432 ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs), 433 ExprKind::Let(..) => true, 434 _ => false, 435 } 436 } 437 438 // We have to take special care for `let` exprs in the condition, e.g. in 439 // `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the 440 // condition in this case. 441 // 442 // In order to maintain the drop behavior for the non `let` parts of the condition, 443 // we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially 444 // gets transformed into `if { let _t = foo; _t } && let pat = val` 445 match &cond.kind { 446 ExprKind::Binary(op @ Spanned { node: ast::BinOpKind::And, .. }, lhs, rhs) 447 if has_let_expr(cond) => 448 { 449 let op = self.lower_binop(*op); 450 let lhs = self.lower_cond(lhs); 451 let rhs = self.lower_cond(rhs); 452 453 self.arena.alloc(self.expr(cond.span, hir::ExprKind::Binary(op, lhs, rhs))) 454 } 455 ExprKind::Let(..) => self.lower_expr(cond), 456 _ => { 457 let cond = self.lower_expr(cond); 458 let reason = DesugaringKind::CondTemporary; 459 let span_block = self.mark_span_with_reason(reason, cond.span, None); 460 self.expr_drop_temps(span_block, cond) 461 } 462 } 463 } 464 465 // We desugar: `'label: while $cond $body` into: 466 // 467 // ``` 468 // 'label: loop { 469 // if { let _t = $cond; _t } { 470 // $body 471 // } 472 // else { 473 // break; 474 // } 475 // } 476 // ``` 477 // 478 // Wrap in a construct equivalent to `{ let _t = $cond; _t }` 479 // to preserve drop semantics since `while $cond { ... }` does not 480 // let temporaries live outside of `cond`. lower_expr_while_in_loop_scope( &mut self, span: Span, cond: &Expr, body: &Block, opt_label: Option<Label>, ) -> hir::ExprKind<'hir>481 fn lower_expr_while_in_loop_scope( 482 &mut self, 483 span: Span, 484 cond: &Expr, 485 body: &Block, 486 opt_label: Option<Label>, 487 ) -> hir::ExprKind<'hir> { 488 let lowered_cond = self.with_loop_condition_scope(|t| t.lower_cond(cond)); 489 let then = self.lower_block_expr(body); 490 let expr_break = self.expr_break(span); 491 let stmt_break = self.stmt_expr(span, expr_break); 492 let else_blk = self.block_all(span, arena_vec![self; stmt_break], None); 493 let else_expr = self.arena.alloc(self.expr_block(else_blk)); 494 let if_kind = hir::ExprKind::If(lowered_cond, self.arena.alloc(then), Some(else_expr)); 495 let if_expr = self.expr(span, if_kind); 496 let block = self.block_expr(self.arena.alloc(if_expr)); 497 let span = self.lower_span(span.with_hi(cond.span.hi())); 498 let opt_label = self.lower_label(opt_label); 499 hir::ExprKind::Loop(block, opt_label, hir::LoopSource::While, span) 500 } 501 502 /// Desugar `try { <stmts>; <expr> }` into `{ <stmts>; ::std::ops::Try::from_output(<expr>) }`, 503 /// `try { <stmts>; }` into `{ <stmts>; ::std::ops::Try::from_output(()) }` 504 /// and save the block id to use it as a break target for desugaring of the `?` operator. lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir>505 fn lower_expr_try_block(&mut self, body: &Block) -> hir::ExprKind<'hir> { 506 self.with_catch_scope(body.id, |this| { 507 let mut block = this.lower_block_noalloc(body, true); 508 509 // Final expression of the block (if present) or `()` with span at the end of block 510 let (try_span, tail_expr) = if let Some(expr) = block.expr.take() { 511 ( 512 this.mark_span_with_reason( 513 DesugaringKind::TryBlock, 514 expr.span, 515 this.allow_try_trait.clone(), 516 ), 517 expr, 518 ) 519 } else { 520 let try_span = this.mark_span_with_reason( 521 DesugaringKind::TryBlock, 522 this.tcx.sess.source_map().end_point(body.span), 523 this.allow_try_trait.clone(), 524 ); 525 526 (try_span, this.expr_unit(try_span)) 527 }; 528 529 let ok_wrapped_span = 530 this.mark_span_with_reason(DesugaringKind::TryBlock, tail_expr.span, None); 531 532 // `::std::ops::Try::from_output($tail_expr)` 533 block.expr = Some(this.wrap_in_try_constructor( 534 hir::LangItem::TryTraitFromOutput, 535 try_span, 536 tail_expr, 537 ok_wrapped_span, 538 )); 539 540 hir::ExprKind::Block(this.arena.alloc(block), None) 541 }) 542 } 543 wrap_in_try_constructor( &mut self, lang_item: hir::LangItem, method_span: Span, expr: &'hir hir::Expr<'hir>, overall_span: Span, ) -> &'hir hir::Expr<'hir>544 fn wrap_in_try_constructor( 545 &mut self, 546 lang_item: hir::LangItem, 547 method_span: Span, 548 expr: &'hir hir::Expr<'hir>, 549 overall_span: Span, 550 ) -> &'hir hir::Expr<'hir> { 551 let constructor = self.arena.alloc(self.expr_lang_item_path(method_span, lang_item, None)); 552 self.expr_call(overall_span, constructor, std::slice::from_ref(expr)) 553 } 554 lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir>555 fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> { 556 let pat = self.lower_pat(&arm.pat); 557 let guard = arm.guard.as_ref().map(|cond| { 558 if let ExprKind::Let(pat, scrutinee, span) = &cond.kind { 559 hir::Guard::IfLet(self.arena.alloc(hir::Let { 560 hir_id: self.next_id(), 561 span: self.lower_span(*span), 562 pat: self.lower_pat(pat), 563 ty: None, 564 init: self.lower_expr(scrutinee), 565 })) 566 } else { 567 hir::Guard::If(self.lower_expr(cond)) 568 } 569 }); 570 let hir_id = self.next_id(); 571 self.lower_attrs(hir_id, &arm.attrs); 572 hir::Arm { 573 hir_id, 574 pat, 575 guard, 576 body: self.lower_expr(&arm.body), 577 span: self.lower_span(arm.span), 578 } 579 } 580 581 /// Lower an `async` construct to a generator that implements `Future`. 582 /// 583 /// This results in: 584 /// 585 /// ```text 586 /// static move? |_task_context| -> <ret_ty> { 587 /// <body> 588 /// } 589 /// ``` make_async_expr( &mut self, capture_clause: CaptureBy, closure_node_id: NodeId, ret_ty: Option<hir::FnRetTy<'hir>>, span: Span, async_gen_kind: hir::AsyncGeneratorKind, body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir>590 pub(super) fn make_async_expr( 591 &mut self, 592 capture_clause: CaptureBy, 593 closure_node_id: NodeId, 594 ret_ty: Option<hir::FnRetTy<'hir>>, 595 span: Span, 596 async_gen_kind: hir::AsyncGeneratorKind, 597 body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, 598 ) -> hir::ExprKind<'hir> { 599 let output = ret_ty.unwrap_or_else(|| hir::FnRetTy::DefaultReturn(self.lower_span(span))); 600 601 // Resume argument type: `ResumeTy` 602 let unstable_span = 603 self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); 604 let resume_ty = hir::QPath::LangItem(hir::LangItem::ResumeTy, unstable_span, None); 605 let input_ty = hir::Ty { 606 hir_id: self.next_id(), 607 kind: hir::TyKind::Path(resume_ty), 608 span: unstable_span, 609 }; 610 611 // The closure/generator `FnDecl` takes a single (resume) argument of type `input_ty`. 612 let fn_decl = self.arena.alloc(hir::FnDecl { 613 inputs: arena_vec![self; input_ty], 614 output, 615 c_variadic: false, 616 implicit_self: hir::ImplicitSelfKind::None, 617 lifetime_elision_allowed: false, 618 }); 619 620 // Lower the argument pattern/ident. The ident is used again in the `.await` lowering. 621 let (pat, task_context_hid) = self.pat_ident_binding_mode( 622 span, 623 Ident::with_dummy_span(sym::_task_context), 624 hir::BindingAnnotation::MUT, 625 ); 626 let param = hir::Param { 627 hir_id: self.next_id(), 628 pat, 629 ty_span: self.lower_span(span), 630 span: self.lower_span(span), 631 }; 632 let params = arena_vec![self; param]; 633 634 let body = self.lower_body(move |this| { 635 this.generator_kind = Some(hir::GeneratorKind::Async(async_gen_kind)); 636 637 let old_ctx = this.task_context; 638 this.task_context = Some(task_context_hid); 639 let res = body(this); 640 this.task_context = old_ctx; 641 (params, res) 642 }); 643 644 // `static |_task_context| -> <ret_ty> { body }`: 645 hir::ExprKind::Closure(self.arena.alloc(hir::Closure { 646 def_id: self.local_def_id(closure_node_id), 647 binder: hir::ClosureBinder::Default, 648 capture_clause, 649 bound_generic_params: &[], 650 fn_decl, 651 body, 652 fn_decl_span: self.lower_span(span), 653 fn_arg_span: None, 654 movability: Some(hir::Movability::Static), 655 constness: hir::Constness::NotConst, 656 })) 657 } 658 659 /// Forwards a possible `#[track_caller]` annotation from `outer_hir_id` to 660 /// `inner_hir_id` in case the `closure_track_caller` feature is enabled. maybe_forward_track_caller( &mut self, span: Span, outer_hir_id: hir::HirId, inner_hir_id: hir::HirId, )661 pub(super) fn maybe_forward_track_caller( 662 &mut self, 663 span: Span, 664 outer_hir_id: hir::HirId, 665 inner_hir_id: hir::HirId, 666 ) { 667 if self.tcx.features().closure_track_caller 668 && let Some(attrs) = self.attrs.get(&outer_hir_id.local_id) 669 && attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)) 670 { 671 let unstable_span = 672 self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone()); 673 self.lower_attrs( 674 inner_hir_id, 675 &[Attribute { 676 kind: AttrKind::Normal(ptr::P(NormalAttr::from_ident(Ident::new(sym::track_caller, span)))), 677 id: self.tcx.sess.parse_sess.attr_id_generator.mk_attr_id(), 678 style: AttrStyle::Outer, 679 span: unstable_span, 680 }], 681 ); 682 } 683 } 684 685 /// Desugar `<expr>.await` into: 686 /// ```ignore (pseudo-rust) 687 /// match ::std::future::IntoFuture::into_future(<expr>) { 688 /// mut __awaitee => loop { 689 /// match unsafe { ::std::future::Future::poll( 690 /// <::std::pin::Pin>::new_unchecked(&mut __awaitee), 691 /// ::std::future::get_context(task_context), 692 /// ) } { 693 /// ::std::task::Poll::Ready(result) => break result, 694 /// ::std::task::Poll::Pending => {} 695 /// } 696 /// task_context = yield (); 697 /// } 698 /// } 699 /// ``` lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir>700 fn lower_expr_await(&mut self, await_kw_span: Span, expr: &Expr) -> hir::ExprKind<'hir> { 701 let full_span = expr.span.to(await_kw_span); 702 match self.generator_kind { 703 Some(hir::GeneratorKind::Async(_)) => {} 704 Some(hir::GeneratorKind::Gen) | None => { 705 self.tcx.sess.emit_err(AwaitOnlyInAsyncFnAndBlocks { 706 await_kw_span, 707 item_span: self.current_item, 708 }); 709 } 710 } 711 let span = self.mark_span_with_reason(DesugaringKind::Await, await_kw_span, None); 712 let gen_future_span = self.mark_span_with_reason( 713 DesugaringKind::Await, 714 full_span, 715 self.allow_gen_future.clone(), 716 ); 717 let expr = self.lower_expr_mut(expr); 718 let expr_hir_id = expr.hir_id; 719 720 // Note that the name of this binding must not be changed to something else because 721 // debuggers and debugger extensions expect it to be called `__awaitee`. They use 722 // this name to identify what is being awaited by a suspended async functions. 723 let awaitee_ident = Ident::with_dummy_span(sym::__awaitee); 724 let (awaitee_pat, awaitee_pat_hid) = 725 self.pat_ident_binding_mode(span, awaitee_ident, hir::BindingAnnotation::MUT); 726 727 let task_context_ident = Ident::with_dummy_span(sym::_task_context); 728 729 // unsafe { 730 // ::std::future::Future::poll( 731 // ::std::pin::Pin::new_unchecked(&mut __awaitee), 732 // ::std::future::get_context(task_context), 733 // ) 734 // } 735 let poll_expr = { 736 let awaitee = self.expr_ident(span, awaitee_ident, awaitee_pat_hid); 737 let ref_mut_awaitee = self.expr_mut_addr_of(span, awaitee); 738 let task_context = if let Some(task_context_hid) = self.task_context { 739 self.expr_ident_mut(span, task_context_ident, task_context_hid) 740 } else { 741 // Use of `await` outside of an async context, we cannot use `task_context` here. 742 self.expr_err(span, self.tcx.sess.delay_span_bug(span, "no task_context hir id")) 743 }; 744 let new_unchecked = self.expr_call_lang_item_fn_mut( 745 span, 746 hir::LangItem::PinNewUnchecked, 747 arena_vec![self; ref_mut_awaitee], 748 Some(expr_hir_id), 749 ); 750 let get_context = self.expr_call_lang_item_fn_mut( 751 gen_future_span, 752 hir::LangItem::GetContext, 753 arena_vec![self; task_context], 754 Some(expr_hir_id), 755 ); 756 let call = self.expr_call_lang_item_fn( 757 span, 758 hir::LangItem::FuturePoll, 759 arena_vec![self; new_unchecked, get_context], 760 Some(expr_hir_id), 761 ); 762 self.arena.alloc(self.expr_unsafe(call)) 763 }; 764 765 // `::std::task::Poll::Ready(result) => break result` 766 let loop_node_id = self.next_node_id(); 767 let loop_hir_id = self.lower_node_id(loop_node_id); 768 let ready_arm = { 769 let x_ident = Ident::with_dummy_span(sym::result); 770 let (x_pat, x_pat_hid) = self.pat_ident(gen_future_span, x_ident); 771 let x_expr = self.expr_ident(gen_future_span, x_ident, x_pat_hid); 772 let ready_field = self.single_pat_field(gen_future_span, x_pat); 773 let ready_pat = self.pat_lang_item_variant( 774 span, 775 hir::LangItem::PollReady, 776 ready_field, 777 Some(expr_hir_id), 778 ); 779 let break_x = self.with_loop_scope(loop_node_id, move |this| { 780 let expr_break = 781 hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr)); 782 this.arena.alloc(this.expr(gen_future_span, expr_break)) 783 }); 784 self.arm(ready_pat, break_x) 785 }; 786 787 // `::std::task::Poll::Pending => {}` 788 let pending_arm = { 789 let pending_pat = self.pat_lang_item_variant( 790 span, 791 hir::LangItem::PollPending, 792 &[], 793 Some(expr_hir_id), 794 ); 795 let empty_block = self.expr_block_empty(span); 796 self.arm(pending_pat, empty_block) 797 }; 798 799 let inner_match_stmt = { 800 let match_expr = self.expr_match( 801 span, 802 poll_expr, 803 arena_vec![self; ready_arm, pending_arm], 804 hir::MatchSource::AwaitDesugar, 805 ); 806 self.stmt_expr(span, match_expr) 807 }; 808 809 // task_context = yield (); 810 let yield_stmt = { 811 let unit = self.expr_unit(span); 812 let yield_expr = self.expr( 813 span, 814 hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }), 815 ); 816 let yield_expr = self.arena.alloc(yield_expr); 817 818 if let Some(task_context_hid) = self.task_context { 819 let lhs = self.expr_ident(span, task_context_ident, task_context_hid); 820 let assign = 821 self.expr(span, hir::ExprKind::Assign(lhs, yield_expr, self.lower_span(span))); 822 self.stmt_expr(span, assign) 823 } else { 824 // Use of `await` outside of an async context. Return `yield_expr` so that we can 825 // proceed with type checking. 826 self.stmt(span, hir::StmtKind::Semi(yield_expr)) 827 } 828 }; 829 830 let loop_block = self.block_all(span, arena_vec![self; inner_match_stmt, yield_stmt], None); 831 832 // loop { .. } 833 let loop_expr = self.arena.alloc(hir::Expr { 834 hir_id: loop_hir_id, 835 kind: hir::ExprKind::Loop( 836 loop_block, 837 None, 838 hir::LoopSource::Loop, 839 self.lower_span(span), 840 ), 841 span: self.lower_span(span), 842 }); 843 844 // mut __awaitee => loop { ... } 845 let awaitee_arm = self.arm(awaitee_pat, loop_expr); 846 847 // `match ::std::future::IntoFuture::into_future(<expr>) { ... }` 848 let into_future_expr = self.expr_call_lang_item_fn( 849 span, 850 hir::LangItem::IntoFutureIntoFuture, 851 arena_vec![self; expr], 852 Some(expr_hir_id), 853 ); 854 855 // match <into_future_expr> { 856 // mut __awaitee => loop { .. } 857 // } 858 hir::ExprKind::Match( 859 into_future_expr, 860 arena_vec![self; awaitee_arm], 861 hir::MatchSource::AwaitDesugar, 862 ) 863 } 864 lower_expr_closure( &mut self, binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, constness: Const, movability: Movability, decl: &FnDecl, body: &Expr, fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir>865 fn lower_expr_closure( 866 &mut self, 867 binder: &ClosureBinder, 868 capture_clause: CaptureBy, 869 closure_id: NodeId, 870 constness: Const, 871 movability: Movability, 872 decl: &FnDecl, 873 body: &Expr, 874 fn_decl_span: Span, 875 fn_arg_span: Span, 876 ) -> hir::ExprKind<'hir> { 877 let (binder_clause, generic_params) = self.lower_closure_binder(binder); 878 879 let (body_id, generator_option) = self.with_new_scopes(move |this| { 880 let prev = this.current_item; 881 this.current_item = Some(fn_decl_span); 882 let mut generator_kind = None; 883 let body_id = this.lower_fn_body(decl, |this| { 884 let e = this.lower_expr_mut(body); 885 generator_kind = this.generator_kind; 886 e 887 }); 888 let generator_option = 889 this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability); 890 this.current_item = prev; 891 (body_id, generator_option) 892 }); 893 894 let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); 895 // Lower outside new scope to preserve `is_in_loop_condition`. 896 let fn_decl = self.lower_fn_decl(decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); 897 898 let c = self.arena.alloc(hir::Closure { 899 def_id: self.local_def_id(closure_id), 900 binder: binder_clause, 901 capture_clause, 902 bound_generic_params, 903 fn_decl, 904 body: body_id, 905 fn_decl_span: self.lower_span(fn_decl_span), 906 fn_arg_span: Some(self.lower_span(fn_arg_span)), 907 movability: generator_option, 908 constness: self.lower_constness(constness), 909 }); 910 911 hir::ExprKind::Closure(c) 912 } 913 generator_movability_for_fn( &mut self, decl: &FnDecl, fn_decl_span: Span, generator_kind: Option<hir::GeneratorKind>, movability: Movability, ) -> Option<hir::Movability>914 fn generator_movability_for_fn( 915 &mut self, 916 decl: &FnDecl, 917 fn_decl_span: Span, 918 generator_kind: Option<hir::GeneratorKind>, 919 movability: Movability, 920 ) -> Option<hir::Movability> { 921 match generator_kind { 922 Some(hir::GeneratorKind::Gen) => { 923 if decl.inputs.len() > 1 { 924 self.tcx.sess.emit_err(GeneratorTooManyParameters { fn_decl_span }); 925 } 926 Some(movability) 927 } 928 Some(hir::GeneratorKind::Async(_)) => { 929 panic!("non-`async` closure body turned `async` during lowering"); 930 } 931 None => { 932 if movability == Movability::Static { 933 self.tcx.sess.emit_err(ClosureCannotBeStatic { fn_decl_span }); 934 } 935 None 936 } 937 } 938 } 939 lower_closure_binder<'c>( &mut self, binder: &'c ClosureBinder, ) -> (hir::ClosureBinder, &'c [GenericParam])940 fn lower_closure_binder<'c>( 941 &mut self, 942 binder: &'c ClosureBinder, 943 ) -> (hir::ClosureBinder, &'c [GenericParam]) { 944 let (binder, params) = match binder { 945 ClosureBinder::NotPresent => (hir::ClosureBinder::Default, &[][..]), 946 ClosureBinder::For { span, generic_params } => { 947 let span = self.lower_span(*span); 948 (hir::ClosureBinder::For { span }, &**generic_params) 949 } 950 }; 951 952 (binder, params) 953 } 954 lower_expr_async_closure( &mut self, binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, closure_hir_id: hir::HirId, inner_closure_id: NodeId, decl: &FnDecl, body: &Expr, fn_decl_span: Span, fn_arg_span: Span, ) -> hir::ExprKind<'hir>955 fn lower_expr_async_closure( 956 &mut self, 957 binder: &ClosureBinder, 958 capture_clause: CaptureBy, 959 closure_id: NodeId, 960 closure_hir_id: hir::HirId, 961 inner_closure_id: NodeId, 962 decl: &FnDecl, 963 body: &Expr, 964 fn_decl_span: Span, 965 fn_arg_span: Span, 966 ) -> hir::ExprKind<'hir> { 967 if let &ClosureBinder::For { span, .. } = binder { 968 self.tcx.sess.emit_err(NotSupportedForLifetimeBinderAsyncClosure { span }); 969 } 970 971 let (binder_clause, generic_params) = self.lower_closure_binder(binder); 972 973 let outer_decl = 974 FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; 975 976 let body = self.with_new_scopes(|this| { 977 // FIXME(cramertj): allow `async` non-`move` closures with arguments. 978 if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { 979 this.tcx.sess.emit_err(AsyncNonMoveClosureNotSupported { fn_decl_span }); 980 } 981 982 // Transform `async |x: u8| -> X { ... }` into 983 // `|x: u8| || -> X { ... }`. 984 let body_id = this.lower_fn_body(&outer_decl, |this| { 985 let async_ret_ty = if let FnRetTy::Ty(ty) = &decl.output { 986 let itctx = ImplTraitContext::Disallowed(ImplTraitPosition::AsyncBlock); 987 Some(hir::FnRetTy::Return(this.lower_ty(&ty, &itctx))) 988 } else { 989 None 990 }; 991 992 let async_body = this.make_async_expr( 993 capture_clause, 994 inner_closure_id, 995 async_ret_ty, 996 body.span, 997 hir::AsyncGeneratorKind::Closure, 998 |this| this.with_new_scopes(|this| this.lower_expr_mut(body)), 999 ); 1000 let hir_id = this.lower_node_id(inner_closure_id); 1001 this.maybe_forward_track_caller(body.span, closure_hir_id, hir_id); 1002 hir::Expr { hir_id, kind: async_body, span: this.lower_span(body.span) } 1003 }); 1004 body_id 1005 }); 1006 1007 let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); 1008 // We need to lower the declaration outside the new scope, because we 1009 // have to conserve the state of being inside a loop condition for the 1010 // closure argument types. 1011 let fn_decl = 1012 self.lower_fn_decl(&outer_decl, closure_id, fn_decl_span, FnDeclKind::Closure, None); 1013 1014 let c = self.arena.alloc(hir::Closure { 1015 def_id: self.local_def_id(closure_id), 1016 binder: binder_clause, 1017 capture_clause, 1018 bound_generic_params, 1019 fn_decl, 1020 body, 1021 fn_decl_span: self.lower_span(fn_decl_span), 1022 fn_arg_span: Some(self.lower_span(fn_arg_span)), 1023 movability: None, 1024 constness: hir::Constness::NotConst, 1025 }); 1026 hir::ExprKind::Closure(c) 1027 } 1028 1029 /// Destructure the LHS of complex assignments. 1030 /// For instance, lower `(a, b) = t` to `{ let (lhs1, lhs2) = t; a = lhs1; b = lhs2; }`. lower_expr_assign( &mut self, lhs: &Expr, rhs: &Expr, eq_sign_span: Span, whole_span: Span, ) -> hir::ExprKind<'hir>1031 fn lower_expr_assign( 1032 &mut self, 1033 lhs: &Expr, 1034 rhs: &Expr, 1035 eq_sign_span: Span, 1036 whole_span: Span, 1037 ) -> hir::ExprKind<'hir> { 1038 // Return early in case of an ordinary assignment. 1039 fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool { 1040 match &lhs.kind { 1041 ExprKind::Array(..) 1042 | ExprKind::Struct(..) 1043 | ExprKind::Tup(..) 1044 | ExprKind::Underscore => false, 1045 // Check for tuple struct constructor. 1046 ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(), 1047 ExprKind::Paren(e) => { 1048 match e.kind { 1049 // We special-case `(..)` for consistency with patterns. 1050 ExprKind::Range(None, None, RangeLimits::HalfOpen) => false, 1051 _ => is_ordinary(lower_ctx, e), 1052 } 1053 } 1054 _ => true, 1055 } 1056 } 1057 if is_ordinary(self, lhs) { 1058 return hir::ExprKind::Assign( 1059 self.lower_expr(lhs), 1060 self.lower_expr(rhs), 1061 self.lower_span(eq_sign_span), 1062 ); 1063 } 1064 1065 let mut assignments = vec![]; 1066 1067 // The LHS becomes a pattern: `(lhs1, lhs2)`. 1068 let pat = self.destructure_assign(lhs, eq_sign_span, &mut assignments); 1069 let rhs = self.lower_expr(rhs); 1070 1071 // Introduce a `let` for destructuring: `let (lhs1, lhs2) = t`. 1072 let destructure_let = self.stmt_let_pat( 1073 None, 1074 whole_span, 1075 Some(rhs), 1076 pat, 1077 hir::LocalSource::AssignDesugar(self.lower_span(eq_sign_span)), 1078 ); 1079 1080 // `a = lhs1; b = lhs2;`. 1081 let stmts = self 1082 .arena 1083 .alloc_from_iter(std::iter::once(destructure_let).chain(assignments.into_iter())); 1084 1085 // Wrap everything in a block. 1086 hir::ExprKind::Block(&self.block_all(whole_span, stmts, None), None) 1087 } 1088 1089 /// If the given expression is a path to a tuple struct, returns that path. 1090 /// It is not a complete check, but just tries to reject most paths early 1091 /// if they are not tuple structs. 1092 /// Type checking will take care of the full validation later. extract_tuple_struct_path<'a>( &mut self, expr: &'a Expr, ) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)>1093 fn extract_tuple_struct_path<'a>( 1094 &mut self, 1095 expr: &'a Expr, 1096 ) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> { 1097 if let ExprKind::Path(qself, path) = &expr.kind { 1098 // Does the path resolve to something disallowed in a tuple struct/variant pattern? 1099 if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { 1100 if let Some(res) = partial_res.full_res() && !res.expected_in_tuple_struct_pat() { 1101 return None; 1102 } 1103 } 1104 return Some((qself, path)); 1105 } 1106 None 1107 } 1108 1109 /// If the given expression is a path to a unit struct, returns that path. 1110 /// It is not a complete check, but just tries to reject most paths early 1111 /// if they are not unit structs. 1112 /// Type checking will take care of the full validation later. extract_unit_struct_path<'a>( &mut self, expr: &'a Expr, ) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)>1113 fn extract_unit_struct_path<'a>( 1114 &mut self, 1115 expr: &'a Expr, 1116 ) -> Option<(&'a Option<AstP<QSelf>>, &'a Path)> { 1117 if let ExprKind::Path(qself, path) = &expr.kind { 1118 // Does the path resolve to something disallowed in a unit struct/variant pattern? 1119 if let Some(partial_res) = self.resolver.get_partial_res(expr.id) { 1120 if let Some(res) = partial_res.full_res() && !res.expected_in_unit_struct_pat() { 1121 return None; 1122 } 1123 } 1124 return Some((qself, path)); 1125 } 1126 None 1127 } 1128 1129 /// Convert the LHS of a destructuring assignment to a pattern. 1130 /// Each sub-assignment is recorded in `assignments`. destructure_assign( &mut self, lhs: &Expr, eq_sign_span: Span, assignments: &mut Vec<hir::Stmt<'hir>>, ) -> &'hir hir::Pat<'hir>1131 fn destructure_assign( 1132 &mut self, 1133 lhs: &Expr, 1134 eq_sign_span: Span, 1135 assignments: &mut Vec<hir::Stmt<'hir>>, 1136 ) -> &'hir hir::Pat<'hir> { 1137 self.arena.alloc(self.destructure_assign_mut(lhs, eq_sign_span, assignments)) 1138 } 1139 destructure_assign_mut( &mut self, lhs: &Expr, eq_sign_span: Span, assignments: &mut Vec<hir::Stmt<'hir>>, ) -> hir::Pat<'hir>1140 fn destructure_assign_mut( 1141 &mut self, 1142 lhs: &Expr, 1143 eq_sign_span: Span, 1144 assignments: &mut Vec<hir::Stmt<'hir>>, 1145 ) -> hir::Pat<'hir> { 1146 match &lhs.kind { 1147 // Underscore pattern. 1148 ExprKind::Underscore => { 1149 return self.pat_without_dbm(lhs.span, hir::PatKind::Wild); 1150 } 1151 // Slice patterns. 1152 ExprKind::Array(elements) => { 1153 let (pats, rest) = 1154 self.destructure_sequence(elements, "slice", eq_sign_span, assignments); 1155 let slice_pat = if let Some((i, span)) = rest { 1156 let (before, after) = pats.split_at(i); 1157 hir::PatKind::Slice( 1158 before, 1159 Some(self.arena.alloc(self.pat_without_dbm(span, hir::PatKind::Wild))), 1160 after, 1161 ) 1162 } else { 1163 hir::PatKind::Slice(pats, None, &[]) 1164 }; 1165 return self.pat_without_dbm(lhs.span, slice_pat); 1166 } 1167 // Tuple structs. 1168 ExprKind::Call(callee, args) => { 1169 if let Some((qself, path)) = self.extract_tuple_struct_path(callee) { 1170 let (pats, rest) = self.destructure_sequence( 1171 args, 1172 "tuple struct or variant", 1173 eq_sign_span, 1174 assignments, 1175 ); 1176 let qpath = self.lower_qpath( 1177 callee.id, 1178 qself, 1179 path, 1180 ParamMode::Optional, 1181 &ImplTraitContext::Disallowed(ImplTraitPosition::Path), 1182 ); 1183 // Destructure like a tuple struct. 1184 let tuple_struct_pat = hir::PatKind::TupleStruct( 1185 qpath, 1186 pats, 1187 hir::DotDotPos::new(rest.map(|r| r.0)), 1188 ); 1189 return self.pat_without_dbm(lhs.span, tuple_struct_pat); 1190 } 1191 } 1192 // Unit structs and enum variants. 1193 ExprKind::Path(..) => { 1194 if let Some((qself, path)) = self.extract_unit_struct_path(lhs) { 1195 let qpath = self.lower_qpath( 1196 lhs.id, 1197 qself, 1198 path, 1199 ParamMode::Optional, 1200 &ImplTraitContext::Disallowed(ImplTraitPosition::Path), 1201 ); 1202 // Destructure like a unit struct. 1203 let unit_struct_pat = hir::PatKind::Path(qpath); 1204 return self.pat_without_dbm(lhs.span, unit_struct_pat); 1205 } 1206 } 1207 // Structs. 1208 ExprKind::Struct(se) => { 1209 let field_pats = self.arena.alloc_from_iter(se.fields.iter().map(|f| { 1210 let pat = self.destructure_assign(&f.expr, eq_sign_span, assignments); 1211 hir::PatField { 1212 hir_id: self.next_id(), 1213 ident: self.lower_ident(f.ident), 1214 pat, 1215 is_shorthand: f.is_shorthand, 1216 span: self.lower_span(f.span), 1217 } 1218 })); 1219 let qpath = self.lower_qpath( 1220 lhs.id, 1221 &se.qself, 1222 &se.path, 1223 ParamMode::Optional, 1224 &ImplTraitContext::Disallowed(ImplTraitPosition::Path), 1225 ); 1226 let fields_omitted = match &se.rest { 1227 StructRest::Base(e) => { 1228 self.tcx.sess.emit_err(FunctionalRecordUpdateDestructuringAssignment { 1229 span: e.span, 1230 }); 1231 true 1232 } 1233 StructRest::Rest(_) => true, 1234 StructRest::None => false, 1235 }; 1236 let struct_pat = hir::PatKind::Struct(qpath, field_pats, fields_omitted); 1237 return self.pat_without_dbm(lhs.span, struct_pat); 1238 } 1239 // Tuples. 1240 ExprKind::Tup(elements) => { 1241 let (pats, rest) = 1242 self.destructure_sequence(elements, "tuple", eq_sign_span, assignments); 1243 let tuple_pat = hir::PatKind::Tuple(pats, hir::DotDotPos::new(rest.map(|r| r.0))); 1244 return self.pat_without_dbm(lhs.span, tuple_pat); 1245 } 1246 ExprKind::Paren(e) => { 1247 // We special-case `(..)` for consistency with patterns. 1248 if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { 1249 let tuple_pat = hir::PatKind::Tuple(&[], hir::DotDotPos::new(Some(0))); 1250 return self.pat_without_dbm(lhs.span, tuple_pat); 1251 } else { 1252 return self.destructure_assign_mut(e, eq_sign_span, assignments); 1253 } 1254 } 1255 _ => {} 1256 } 1257 // Treat all other cases as normal lvalue. 1258 let ident = Ident::new(sym::lhs, self.lower_span(lhs.span)); 1259 let (pat, binding) = self.pat_ident_mut(lhs.span, ident); 1260 let ident = self.expr_ident(lhs.span, ident, binding); 1261 let assign = 1262 hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span)); 1263 let expr = self.expr(lhs.span, assign); 1264 assignments.push(self.stmt_expr(lhs.span, expr)); 1265 pat 1266 } 1267 1268 /// Destructure a sequence of expressions occurring on the LHS of an assignment. 1269 /// Such a sequence occurs in a tuple (struct)/slice. 1270 /// Return a sequence of corresponding patterns, and the index and the span of `..` if it 1271 /// exists. 1272 /// Each sub-assignment is recorded in `assignments`. destructure_sequence( &mut self, elements: &[AstP<Expr>], ctx: &str, eq_sign_span: Span, assignments: &mut Vec<hir::Stmt<'hir>>, ) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>)1273 fn destructure_sequence( 1274 &mut self, 1275 elements: &[AstP<Expr>], 1276 ctx: &str, 1277 eq_sign_span: Span, 1278 assignments: &mut Vec<hir::Stmt<'hir>>, 1279 ) -> (&'hir [hir::Pat<'hir>], Option<(usize, Span)>) { 1280 let mut rest = None; 1281 let elements = 1282 self.arena.alloc_from_iter(elements.iter().enumerate().filter_map(|(i, e)| { 1283 // Check for `..` pattern. 1284 if let ExprKind::Range(None, None, RangeLimits::HalfOpen) = e.kind { 1285 if let Some((_, prev_span)) = rest { 1286 self.ban_extra_rest_pat(e.span, prev_span, ctx); 1287 } else { 1288 rest = Some((i, e.span)); 1289 } 1290 None 1291 } else { 1292 Some(self.destructure_assign_mut(e, eq_sign_span, assignments)) 1293 } 1294 })); 1295 (elements, rest) 1296 } 1297 1298 /// Desugar `<start>..=<end>` into `std::ops::RangeInclusive::new(<start>, <end>)`. lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir>1299 fn lower_expr_range_closed(&mut self, span: Span, e1: &Expr, e2: &Expr) -> hir::ExprKind<'hir> { 1300 let e1 = self.lower_expr_mut(e1); 1301 let e2 = self.lower_expr_mut(e2); 1302 let fn_path = 1303 hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None); 1304 let fn_expr = self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path))); 1305 hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2]) 1306 } 1307 lower_expr_range( &mut self, span: Span, e1: Option<&Expr>, e2: Option<&Expr>, lims: RangeLimits, ) -> hir::ExprKind<'hir>1308 fn lower_expr_range( 1309 &mut self, 1310 span: Span, 1311 e1: Option<&Expr>, 1312 e2: Option<&Expr>, 1313 lims: RangeLimits, 1314 ) -> hir::ExprKind<'hir> { 1315 use rustc_ast::RangeLimits::*; 1316 1317 let lang_item = match (e1, e2, lims) { 1318 (None, None, HalfOpen) => hir::LangItem::RangeFull, 1319 (Some(..), None, HalfOpen) => hir::LangItem::RangeFrom, 1320 (None, Some(..), HalfOpen) => hir::LangItem::RangeTo, 1321 (Some(..), Some(..), HalfOpen) => hir::LangItem::Range, 1322 (None, Some(..), Closed) => hir::LangItem::RangeToInclusive, 1323 (Some(..), Some(..), Closed) => unreachable!(), 1324 (start, None, Closed) => { 1325 self.tcx.sess.emit_err(InclusiveRangeWithNoEnd { span }); 1326 match start { 1327 Some(..) => hir::LangItem::RangeFrom, 1328 None => hir::LangItem::RangeFull, 1329 } 1330 } 1331 }; 1332 1333 let fields = self.arena.alloc_from_iter( 1334 e1.iter().map(|e| (sym::start, e)).chain(e2.iter().map(|e| (sym::end, e))).map( 1335 |(s, e)| { 1336 let expr = self.lower_expr(&e); 1337 let ident = Ident::new(s, self.lower_span(e.span)); 1338 self.expr_field(ident, expr, e.span) 1339 }, 1340 ), 1341 ); 1342 1343 hir::ExprKind::Struct( 1344 self.arena.alloc(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), 1345 fields, 1346 None, 1347 ) 1348 } 1349 lower_label(&self, opt_label: Option<Label>) -> Option<Label>1350 fn lower_label(&self, opt_label: Option<Label>) -> Option<Label> { 1351 let label = opt_label?; 1352 Some(Label { ident: self.lower_ident(label.ident) }) 1353 } 1354 lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination1355 fn lower_loop_destination(&mut self, destination: Option<(NodeId, Label)>) -> hir::Destination { 1356 let target_id = match destination { 1357 Some((id, _)) => { 1358 if let Some(loop_id) = self.resolver.get_label_res(id) { 1359 Ok(self.lower_node_id(loop_id)) 1360 } else { 1361 Err(hir::LoopIdError::UnresolvedLabel) 1362 } 1363 } 1364 None => self 1365 .loop_scope 1366 .map(|id| Ok(self.lower_node_id(id))) 1367 .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)), 1368 }; 1369 let label = self.lower_label(destination.map(|(_, label)| label)); 1370 hir::Destination { label, target_id } 1371 } 1372 lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination1373 fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination { 1374 if self.is_in_loop_condition && opt_label.is_none() { 1375 hir::Destination { 1376 label: None, 1377 target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition), 1378 } 1379 } else { 1380 self.lower_loop_destination(opt_label.map(|label| (id, label))) 1381 } 1382 } 1383 with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T1384 fn with_catch_scope<T>(&mut self, catch_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { 1385 let old_scope = self.catch_scope.replace(catch_id); 1386 let result = f(self); 1387 self.catch_scope = old_scope; 1388 result 1389 } 1390 with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T1391 fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T { 1392 // We're no longer in the base loop's condition; we're in another loop. 1393 let was_in_loop_condition = self.is_in_loop_condition; 1394 self.is_in_loop_condition = false; 1395 1396 let old_scope = self.loop_scope.replace(loop_id); 1397 let result = f(self); 1398 self.loop_scope = old_scope; 1399 1400 self.is_in_loop_condition = was_in_loop_condition; 1401 1402 result 1403 } 1404 with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T1405 fn with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { 1406 let was_in_loop_condition = self.is_in_loop_condition; 1407 self.is_in_loop_condition = true; 1408 1409 let result = f(self); 1410 1411 self.is_in_loop_condition = was_in_loop_condition; 1412 1413 result 1414 } 1415 lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir>1416 fn lower_expr_field(&mut self, f: &ExprField) -> hir::ExprField<'hir> { 1417 let hir_id = self.lower_node_id(f.id); 1418 self.lower_attrs(hir_id, &f.attrs); 1419 hir::ExprField { 1420 hir_id, 1421 ident: self.lower_ident(f.ident), 1422 expr: self.lower_expr(&f.expr), 1423 span: self.lower_span(f.span), 1424 is_shorthand: f.is_shorthand, 1425 } 1426 } 1427 lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir>1428 fn lower_expr_yield(&mut self, span: Span, opt_expr: Option<&Expr>) -> hir::ExprKind<'hir> { 1429 match self.generator_kind { 1430 Some(hir::GeneratorKind::Gen) => {} 1431 Some(hir::GeneratorKind::Async(_)) => { 1432 self.tcx.sess.emit_err(AsyncGeneratorsNotSupported { span }); 1433 } 1434 None => self.generator_kind = Some(hir::GeneratorKind::Gen), 1435 } 1436 1437 let expr = 1438 opt_expr.as_ref().map(|x| self.lower_expr(x)).unwrap_or_else(|| self.expr_unit(span)); 1439 1440 hir::ExprKind::Yield(expr, hir::YieldSource::Yield) 1441 } 1442 1443 /// Desugar `ExprForLoop` from: `[opt_ident]: for <pat> in <head> <body>` into: 1444 /// ```ignore (pseudo-rust) 1445 /// { 1446 /// let result = match IntoIterator::into_iter(<head>) { 1447 /// mut iter => { 1448 /// [opt_ident]: loop { 1449 /// match Iterator::next(&mut iter) { 1450 /// None => break, 1451 /// Some(<pat>) => <body>, 1452 /// }; 1453 /// } 1454 /// } 1455 /// }; 1456 /// result 1457 /// } 1458 /// ``` lower_expr_for( &mut self, e: &Expr, pat: &Pat, head: &Expr, body: &Block, opt_label: Option<Label>, ) -> hir::Expr<'hir>1459 fn lower_expr_for( 1460 &mut self, 1461 e: &Expr, 1462 pat: &Pat, 1463 head: &Expr, 1464 body: &Block, 1465 opt_label: Option<Label>, 1466 ) -> hir::Expr<'hir> { 1467 let head = self.lower_expr_mut(head); 1468 let pat = self.lower_pat(pat); 1469 let for_span = 1470 self.mark_span_with_reason(DesugaringKind::ForLoop, self.lower_span(e.span), None); 1471 let head_span = self.mark_span_with_reason(DesugaringKind::ForLoop, head.span, None); 1472 let pat_span = self.mark_span_with_reason(DesugaringKind::ForLoop, pat.span, None); 1473 1474 // `None => break` 1475 let none_arm = { 1476 let break_expr = self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span)); 1477 let pat = self.pat_none(for_span); 1478 self.arm(pat, break_expr) 1479 }; 1480 1481 // Some(<pat>) => <body>, 1482 let some_arm = { 1483 let some_pat = self.pat_some(pat_span, pat); 1484 let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false)); 1485 let body_expr = self.arena.alloc(self.expr_block(body_block)); 1486 self.arm(some_pat, body_expr) 1487 }; 1488 1489 // `mut iter` 1490 let iter = Ident::with_dummy_span(sym::iter); 1491 let (iter_pat, iter_pat_nid) = 1492 self.pat_ident_binding_mode(head_span, iter, hir::BindingAnnotation::MUT); 1493 1494 // `match Iterator::next(&mut iter) { ... }` 1495 let match_expr = { 1496 let iter = self.expr_ident(head_span, iter, iter_pat_nid); 1497 let ref_mut_iter = self.expr_mut_addr_of(head_span, iter); 1498 let next_expr = self.expr_call_lang_item_fn( 1499 head_span, 1500 hir::LangItem::IteratorNext, 1501 arena_vec![self; ref_mut_iter], 1502 None, 1503 ); 1504 let arms = arena_vec![self; none_arm, some_arm]; 1505 1506 self.expr_match(head_span, next_expr, arms, hir::MatchSource::ForLoopDesugar) 1507 }; 1508 let match_stmt = self.stmt_expr(for_span, match_expr); 1509 1510 let loop_block = self.block_all(for_span, arena_vec![self; match_stmt], None); 1511 1512 // `[opt_ident]: loop { ... }` 1513 let kind = hir::ExprKind::Loop( 1514 loop_block, 1515 self.lower_label(opt_label), 1516 hir::LoopSource::ForLoop, 1517 self.lower_span(for_span.with_hi(head.span.hi())), 1518 ); 1519 let loop_expr = 1520 self.arena.alloc(hir::Expr { hir_id: self.lower_node_id(e.id), kind, span: for_span }); 1521 1522 // `mut iter => { ... }` 1523 let iter_arm = self.arm(iter_pat, loop_expr); 1524 1525 // `match ::std::iter::IntoIterator::into_iter(<head>) { ... }` 1526 let into_iter_expr = { 1527 self.expr_call_lang_item_fn( 1528 head_span, 1529 hir::LangItem::IntoIterIntoIter, 1530 arena_vec![self; head], 1531 None, 1532 ) 1533 }; 1534 1535 let match_expr = self.arena.alloc(self.expr_match( 1536 for_span, 1537 into_iter_expr, 1538 arena_vec![self; iter_arm], 1539 hir::MatchSource::ForLoopDesugar, 1540 )); 1541 1542 // This is effectively `{ let _result = ...; _result }`. 1543 // The construct was introduced in #21984 and is necessary to make sure that 1544 // temporaries in the `head` expression are dropped and do not leak to the 1545 // surrounding scope of the `match` since the `match` is not a terminating scope. 1546 // 1547 // Also, add the attributes to the outer returned expr node. 1548 let expr = self.expr_drop_temps_mut(for_span, match_expr); 1549 self.lower_attrs(expr.hir_id, &e.attrs); 1550 expr 1551 } 1552 1553 /// Desugar `ExprKind::Try` from: `<expr>?` into: 1554 /// ```ignore (pseudo-rust) 1555 /// match Try::branch(<expr>) { 1556 /// ControlFlow::Continue(val) => #[allow(unreachable_code)] val,, 1557 /// ControlFlow::Break(residual) => 1558 /// #[allow(unreachable_code)] 1559 /// // If there is an enclosing `try {...}`: 1560 /// break 'catch_target Try::from_residual(residual), 1561 /// // Otherwise: 1562 /// return Try::from_residual(residual), 1563 /// } 1564 /// ``` lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir>1565 fn lower_expr_try(&mut self, span: Span, sub_expr: &Expr) -> hir::ExprKind<'hir> { 1566 let unstable_span = self.mark_span_with_reason( 1567 DesugaringKind::QuestionMark, 1568 span, 1569 self.allow_try_trait.clone(), 1570 ); 1571 let try_span = self.tcx.sess.source_map().end_point(span); 1572 let try_span = self.mark_span_with_reason( 1573 DesugaringKind::QuestionMark, 1574 try_span, 1575 self.allow_try_trait.clone(), 1576 ); 1577 1578 // `Try::branch(<expr>)` 1579 let scrutinee = { 1580 // expand <expr> 1581 let sub_expr = self.lower_expr_mut(sub_expr); 1582 1583 self.expr_call_lang_item_fn( 1584 unstable_span, 1585 hir::LangItem::TryTraitBranch, 1586 arena_vec![self; sub_expr], 1587 None, 1588 ) 1589 }; 1590 1591 // `#[allow(unreachable_code)]` 1592 let attr = attr::mk_attr_nested_word( 1593 &self.tcx.sess.parse_sess.attr_id_generator, 1594 AttrStyle::Outer, 1595 sym::allow, 1596 sym::unreachable_code, 1597 self.lower_span(span), 1598 ); 1599 let attrs: AttrVec = thin_vec![attr]; 1600 1601 // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,` 1602 let continue_arm = { 1603 let val_ident = Ident::with_dummy_span(sym::val); 1604 let (val_pat, val_pat_nid) = self.pat_ident(span, val_ident); 1605 let val_expr = self.expr_ident(span, val_ident, val_pat_nid); 1606 self.lower_attrs(val_expr.hir_id, &attrs); 1607 let continue_pat = self.pat_cf_continue(unstable_span, val_pat); 1608 self.arm(continue_pat, val_expr) 1609 }; 1610 1611 // `ControlFlow::Break(residual) => 1612 // #[allow(unreachable_code)] 1613 // return Try::from_residual(residual),` 1614 let break_arm = { 1615 let residual_ident = Ident::with_dummy_span(sym::residual); 1616 let (residual_local, residual_local_nid) = self.pat_ident(try_span, residual_ident); 1617 let residual_expr = self.expr_ident_mut(try_span, residual_ident, residual_local_nid); 1618 let from_residual_expr = self.wrap_in_try_constructor( 1619 hir::LangItem::TryTraitFromResidual, 1620 try_span, 1621 self.arena.alloc(residual_expr), 1622 unstable_span, 1623 ); 1624 let ret_expr = if let Some(catch_node) = self.catch_scope { 1625 let target_id = Ok(self.lower_node_id(catch_node)); 1626 self.arena.alloc(self.expr( 1627 try_span, 1628 hir::ExprKind::Break( 1629 hir::Destination { label: None, target_id }, 1630 Some(from_residual_expr), 1631 ), 1632 )) 1633 } else { 1634 self.arena.alloc(self.expr(try_span, hir::ExprKind::Ret(Some(from_residual_expr)))) 1635 }; 1636 self.lower_attrs(ret_expr.hir_id, &attrs); 1637 1638 let break_pat = self.pat_cf_break(try_span, residual_local); 1639 self.arm(break_pat, ret_expr) 1640 }; 1641 1642 hir::ExprKind::Match( 1643 scrutinee, 1644 arena_vec![self; break_arm, continue_arm], 1645 hir::MatchSource::TryDesugar, 1646 ) 1647 } 1648 1649 /// Desugar `ExprKind::Yeet` from: `do yeet <expr>` into: 1650 /// ```ignore(illustrative) 1651 /// // If there is an enclosing `try {...}`: 1652 /// break 'catch_target FromResidual::from_residual(Yeet(residual)); 1653 /// // Otherwise: 1654 /// return FromResidual::from_residual(Yeet(residual)); 1655 /// ``` 1656 /// But to simplify this, there's a `from_yeet` lang item function which 1657 /// handles the combined `FromResidual::from_residual(Yeet(residual))`. lower_expr_yeet(&mut self, span: Span, sub_expr: Option<&Expr>) -> hir::ExprKind<'hir>1658 fn lower_expr_yeet(&mut self, span: Span, sub_expr: Option<&Expr>) -> hir::ExprKind<'hir> { 1659 // The expression (if present) or `()` otherwise. 1660 let (yeeted_span, yeeted_expr) = if let Some(sub_expr) = sub_expr { 1661 (sub_expr.span, self.lower_expr(sub_expr)) 1662 } else { 1663 (self.mark_span_with_reason(DesugaringKind::YeetExpr, span, None), self.expr_unit(span)) 1664 }; 1665 1666 let unstable_span = self.mark_span_with_reason( 1667 DesugaringKind::YeetExpr, 1668 span, 1669 self.allow_try_trait.clone(), 1670 ); 1671 1672 let from_yeet_expr = self.wrap_in_try_constructor( 1673 hir::LangItem::TryTraitFromYeet, 1674 unstable_span, 1675 yeeted_expr, 1676 yeeted_span, 1677 ); 1678 1679 if let Some(catch_node) = self.catch_scope { 1680 let target_id = Ok(self.lower_node_id(catch_node)); 1681 hir::ExprKind::Break(hir::Destination { label: None, target_id }, Some(from_yeet_expr)) 1682 } else { 1683 hir::ExprKind::Ret(Some(from_yeet_expr)) 1684 } 1685 } 1686 1687 // ========================================================================= 1688 // Helper methods for building HIR. 1689 // ========================================================================= 1690 1691 /// Wrap the given `expr` in a terminating scope using `hir::ExprKind::DropTemps`. 1692 /// 1693 /// In terms of drop order, it has the same effect as wrapping `expr` in 1694 /// `{ let _t = $expr; _t }` but should provide better compile-time performance. 1695 /// 1696 /// The drop order can be important in e.g. `if expr { .. }`. expr_drop_temps( &mut self, span: Span, expr: &'hir hir::Expr<'hir>, ) -> &'hir hir::Expr<'hir>1697 pub(super) fn expr_drop_temps( 1698 &mut self, 1699 span: Span, 1700 expr: &'hir hir::Expr<'hir>, 1701 ) -> &'hir hir::Expr<'hir> { 1702 self.arena.alloc(self.expr_drop_temps_mut(span, expr)) 1703 } 1704 expr_drop_temps_mut( &mut self, span: Span, expr: &'hir hir::Expr<'hir>, ) -> hir::Expr<'hir>1705 pub(super) fn expr_drop_temps_mut( 1706 &mut self, 1707 span: Span, 1708 expr: &'hir hir::Expr<'hir>, 1709 ) -> hir::Expr<'hir> { 1710 self.expr(span, hir::ExprKind::DropTemps(expr)) 1711 } 1712 expr_match( &mut self, span: Span, arg: &'hir hir::Expr<'hir>, arms: &'hir [hir::Arm<'hir>], source: hir::MatchSource, ) -> hir::Expr<'hir>1713 pub(super) fn expr_match( 1714 &mut self, 1715 span: Span, 1716 arg: &'hir hir::Expr<'hir>, 1717 arms: &'hir [hir::Arm<'hir>], 1718 source: hir::MatchSource, 1719 ) -> hir::Expr<'hir> { 1720 self.expr(span, hir::ExprKind::Match(arg, arms, source)) 1721 } 1722 expr_break(&mut self, span: Span) -> hir::Expr<'hir>1723 fn expr_break(&mut self, span: Span) -> hir::Expr<'hir> { 1724 let expr_break = hir::ExprKind::Break(self.lower_loop_destination(None), None); 1725 self.expr(span, expr_break) 1726 } 1727 expr_break_alloc(&mut self, span: Span) -> &'hir hir::Expr<'hir>1728 fn expr_break_alloc(&mut self, span: Span) -> &'hir hir::Expr<'hir> { 1729 let expr_break = self.expr_break(span); 1730 self.arena.alloc(expr_break) 1731 } 1732 expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir>1733 fn expr_mut_addr_of(&mut self, span: Span, e: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> { 1734 self.expr(span, hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e)) 1735 } 1736 expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir>1737 fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> { 1738 self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]))) 1739 } 1740 expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir>1741 pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> { 1742 let lit = self.arena.alloc(hir::Lit { 1743 span: sp, 1744 node: ast::LitKind::Int(value as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)), 1745 }); 1746 self.expr(sp, hir::ExprKind::Lit(lit)) 1747 } 1748 expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir>1749 pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> { 1750 let lit = self.arena.alloc(hir::Lit { 1751 span: sp, 1752 node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)), 1753 }); 1754 self.expr(sp, hir::ExprKind::Lit(lit)) 1755 } 1756 expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir>1757 pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> { 1758 let lit = self.arena.alloc(hir::Lit { span: sp, node: ast::LitKind::Char(value) }); 1759 self.expr(sp, hir::ExprKind::Lit(lit)) 1760 } 1761 expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir>1762 pub(super) fn expr_str(&mut self, sp: Span, value: Symbol) -> hir::Expr<'hir> { 1763 let lit = self 1764 .arena 1765 .alloc(hir::Lit { span: sp, node: ast::LitKind::Str(value, ast::StrStyle::Cooked) }); 1766 self.expr(sp, hir::ExprKind::Lit(lit)) 1767 } 1768 expr_call_mut( &mut self, span: Span, e: &'hir hir::Expr<'hir>, args: &'hir [hir::Expr<'hir>], ) -> hir::Expr<'hir>1769 pub(super) fn expr_call_mut( 1770 &mut self, 1771 span: Span, 1772 e: &'hir hir::Expr<'hir>, 1773 args: &'hir [hir::Expr<'hir>], 1774 ) -> hir::Expr<'hir> { 1775 self.expr(span, hir::ExprKind::Call(e, args)) 1776 } 1777 expr_call( &mut self, span: Span, e: &'hir hir::Expr<'hir>, args: &'hir [hir::Expr<'hir>], ) -> &'hir hir::Expr<'hir>1778 pub(super) fn expr_call( 1779 &mut self, 1780 span: Span, 1781 e: &'hir hir::Expr<'hir>, 1782 args: &'hir [hir::Expr<'hir>], 1783 ) -> &'hir hir::Expr<'hir> { 1784 self.arena.alloc(self.expr_call_mut(span, e, args)) 1785 } 1786 expr_call_lang_item_fn_mut( &mut self, span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], hir_id: Option<hir::HirId>, ) -> hir::Expr<'hir>1787 fn expr_call_lang_item_fn_mut( 1788 &mut self, 1789 span: Span, 1790 lang_item: hir::LangItem, 1791 args: &'hir [hir::Expr<'hir>], 1792 hir_id: Option<hir::HirId>, 1793 ) -> hir::Expr<'hir> { 1794 let path = self.arena.alloc(self.expr_lang_item_path(span, lang_item, hir_id)); 1795 self.expr_call_mut(span, path, args) 1796 } 1797 expr_call_lang_item_fn( &mut self, span: Span, lang_item: hir::LangItem, args: &'hir [hir::Expr<'hir>], hir_id: Option<hir::HirId>, ) -> &'hir hir::Expr<'hir>1798 fn expr_call_lang_item_fn( 1799 &mut self, 1800 span: Span, 1801 lang_item: hir::LangItem, 1802 args: &'hir [hir::Expr<'hir>], 1803 hir_id: Option<hir::HirId>, 1804 ) -> &'hir hir::Expr<'hir> { 1805 self.arena.alloc(self.expr_call_lang_item_fn_mut(span, lang_item, args, hir_id)) 1806 } 1807 expr_lang_item_path( &mut self, span: Span, lang_item: hir::LangItem, hir_id: Option<hir::HirId>, ) -> hir::Expr<'hir>1808 fn expr_lang_item_path( 1809 &mut self, 1810 span: Span, 1811 lang_item: hir::LangItem, 1812 hir_id: Option<hir::HirId>, 1813 ) -> hir::Expr<'hir> { 1814 self.expr( 1815 span, 1816 hir::ExprKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), hir_id)), 1817 ) 1818 } 1819 1820 /// `<LangItem>::name` expr_lang_item_type_relative( &mut self, span: Span, lang_item: hir::LangItem, name: Symbol, ) -> hir::Expr<'hir>1821 pub(super) fn expr_lang_item_type_relative( 1822 &mut self, 1823 span: Span, 1824 lang_item: hir::LangItem, 1825 name: Symbol, 1826 ) -> hir::Expr<'hir> { 1827 let path = hir::ExprKind::Path(hir::QPath::TypeRelative( 1828 self.arena.alloc(self.ty( 1829 span, 1830 hir::TyKind::Path(hir::QPath::LangItem(lang_item, self.lower_span(span), None)), 1831 )), 1832 self.arena.alloc(hir::PathSegment::new( 1833 Ident::new(name, span), 1834 self.next_id(), 1835 Res::Err, 1836 )), 1837 )); 1838 self.expr(span, path) 1839 } 1840 expr_ident( &mut self, sp: Span, ident: Ident, binding: hir::HirId, ) -> &'hir hir::Expr<'hir>1841 pub(super) fn expr_ident( 1842 &mut self, 1843 sp: Span, 1844 ident: Ident, 1845 binding: hir::HirId, 1846 ) -> &'hir hir::Expr<'hir> { 1847 self.arena.alloc(self.expr_ident_mut(sp, ident, binding)) 1848 } 1849 expr_ident_mut( &mut self, span: Span, ident: Ident, binding: hir::HirId, ) -> hir::Expr<'hir>1850 pub(super) fn expr_ident_mut( 1851 &mut self, 1852 span: Span, 1853 ident: Ident, 1854 binding: hir::HirId, 1855 ) -> hir::Expr<'hir> { 1856 let hir_id = self.next_id(); 1857 let res = Res::Local(binding); 1858 let expr_path = hir::ExprKind::Path(hir::QPath::Resolved( 1859 None, 1860 self.arena.alloc(hir::Path { 1861 span: self.lower_span(span), 1862 res, 1863 segments: arena_vec![self; hir::PathSegment::new(ident, hir_id, res)], 1864 }), 1865 )); 1866 1867 self.expr(span, expr_path) 1868 } 1869 expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir>1870 fn expr_unsafe(&mut self, expr: &'hir hir::Expr<'hir>) -> hir::Expr<'hir> { 1871 let hir_id = self.next_id(); 1872 let span = expr.span; 1873 self.expr( 1874 span, 1875 hir::ExprKind::Block( 1876 self.arena.alloc(hir::Block { 1877 stmts: &[], 1878 expr: Some(expr), 1879 hir_id, 1880 rules: hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated), 1881 span: self.lower_span(span), 1882 targeted_by_break: false, 1883 }), 1884 None, 1885 ), 1886 ) 1887 } 1888 expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir>1889 fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> { 1890 let blk = self.block_all(span, &[], None); 1891 let expr = self.expr_block(blk); 1892 self.arena.alloc(expr) 1893 } 1894 expr_block(&mut self, b: &'hir hir::Block<'hir>) -> hir::Expr<'hir>1895 pub(super) fn expr_block(&mut self, b: &'hir hir::Block<'hir>) -> hir::Expr<'hir> { 1896 self.expr(b.span, hir::ExprKind::Block(b, None)) 1897 } 1898 expr_array_ref( &mut self, span: Span, elements: &'hir [hir::Expr<'hir>], ) -> hir::Expr<'hir>1899 pub(super) fn expr_array_ref( 1900 &mut self, 1901 span: Span, 1902 elements: &'hir [hir::Expr<'hir>], 1903 ) -> hir::Expr<'hir> { 1904 let addrof = hir::ExprKind::AddrOf( 1905 hir::BorrowKind::Ref, 1906 hir::Mutability::Not, 1907 self.arena.alloc(self.expr(span, hir::ExprKind::Array(elements))), 1908 ); 1909 self.expr(span, addrof) 1910 } 1911 expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir>1912 pub(super) fn expr(&mut self, span: Span, kind: hir::ExprKind<'hir>) -> hir::Expr<'hir> { 1913 let hir_id = self.next_id(); 1914 hir::Expr { hir_id, kind, span: self.lower_span(span) } 1915 } 1916 expr_field( &mut self, ident: Ident, expr: &'hir hir::Expr<'hir>, span: Span, ) -> hir::ExprField<'hir>1917 pub(super) fn expr_field( 1918 &mut self, 1919 ident: Ident, 1920 expr: &'hir hir::Expr<'hir>, 1921 span: Span, 1922 ) -> hir::ExprField<'hir> { 1923 hir::ExprField { 1924 hir_id: self.next_id(), 1925 ident, 1926 span: self.lower_span(span), 1927 expr, 1928 is_shorthand: false, 1929 } 1930 } 1931 arm( &mut self, pat: &'hir hir::Pat<'hir>, expr: &'hir hir::Expr<'hir>, ) -> hir::Arm<'hir>1932 pub(super) fn arm( 1933 &mut self, 1934 pat: &'hir hir::Pat<'hir>, 1935 expr: &'hir hir::Expr<'hir>, 1936 ) -> hir::Arm<'hir> { 1937 hir::Arm { 1938 hir_id: self.next_id(), 1939 pat, 1940 guard: None, 1941 span: self.lower_span(expr.span), 1942 body: expr, 1943 } 1944 } 1945 } 1946