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