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