- id: e.id,
- node: match e.node {
- ExprBox(ref e) => {
- hir::ExprBox(lower_expr(lctx, e))
- }
- ExprVec(ref exprs) => {
- hir::ExprVec(exprs.iter().map(|x| lower_expr(lctx, x)).collect())
- }
- ExprRepeat(ref expr, ref count) => {
- hir::ExprRepeat(lower_expr(lctx, expr), lower_expr(lctx, count))
- }
- ExprTup(ref elts) => {
- hir::ExprTup(elts.iter().map(|x| lower_expr(lctx, x)).collect())
- }
- ExprCall(ref f, ref args) => {
- hir::ExprCall(lower_expr(lctx, f),
- args.iter().map(|x| lower_expr(lctx, x)).collect())
- }
- ExprMethodCall(i, ref tps, ref args) => {
- hir::ExprMethodCall(
- respan(i.span, i.node.name),
- tps.iter().map(|x| lower_ty(lctx, x)).collect(),
- args.iter().map(|x| lower_expr(lctx, x)).collect())
- }
- ExprBinary(binop, ref lhs, ref rhs) => {
- hir::ExprBinary(lower_binop(lctx, binop),
- lower_expr(lctx, lhs),
- lower_expr(lctx, rhs))
- }
- ExprUnary(op, ref ohs) => {
- hir::ExprUnary(lower_unop(lctx, op), lower_expr(lctx, ohs))
- }
- ExprLit(ref l) => hir::ExprLit(P((**l).clone())),
- ExprCast(ref expr, ref ty) => {
- hir::ExprCast(lower_expr(lctx, expr), lower_ty(lctx, ty))
- }
- ExprAddrOf(m, ref ohs) => {
- hir::ExprAddrOf(lower_mutability(lctx, m), lower_expr(lctx, ohs))
- }
- ExprIf(ref cond, ref tr, ref fl) => {
- hir::ExprIf(lower_expr(lctx, cond),
- lower_block(lctx, tr),
- fl.as_ref().map(|x| lower_expr(lctx, x)))
- }
- ExprWhile(ref cond, ref body, opt_ident) => {
- hir::ExprWhile(lower_expr(lctx, cond),
- lower_block(lctx, body),
- opt_ident)
- }
- ExprLoop(ref body, opt_ident) => {
- hir::ExprLoop(lower_block(lctx, body),
- opt_ident)
- }
- ExprMatch(ref expr, ref arms, ref source) => {
- hir::ExprMatch(lower_expr(lctx, expr),
- arms.iter().map(|x| lower_arm(lctx, x)).collect(),
- lower_match_source(lctx, source))
- }
- ExprClosure(capture_clause, ref decl, ref body) => {
- hir::ExprClosure(lower_capture_clause(lctx, capture_clause),
- lower_fn_decl(lctx, decl),
- lower_block(lctx, body))
- }
- ExprBlock(ref blk) => hir::ExprBlock(lower_block(lctx, blk)),
- ExprAssign(ref el, ref er) => {
- hir::ExprAssign(lower_expr(lctx, el), lower_expr(lctx, er))
- }
- ExprAssignOp(op, ref el, ref er) => {
- hir::ExprAssignOp(lower_binop(lctx, op),
- lower_expr(lctx, el),
- lower_expr(lctx, er))
- }
- ExprField(ref el, ident) => {
- hir::ExprField(lower_expr(lctx, el), respan(ident.span, ident.node.name))
- }
- ExprTupField(ref el, ident) => {
- hir::ExprTupField(lower_expr(lctx, el), ident)
- }
- ExprIndex(ref el, ref er) => {
- hir::ExprIndex(lower_expr(lctx, el), lower_expr(lctx, er))
- }
- ExprRange(ref e1, ref e2) => {
- hir::ExprRange(e1.as_ref().map(|x| lower_expr(lctx, x)),
- e2.as_ref().map(|x| lower_expr(lctx, x)))
- }
- ExprPath(ref qself, ref path) => {
- let qself = qself.as_ref().map(|&QSelf { ref ty, position }| {
- hir::QSelf {
- ty: lower_ty(lctx, ty),
- position: position
+ id: e.id,
+ node: match e.node {
+ // Issue #22181:
+ // Eventually a desugaring for `box EXPR`
+ // (similar to the desugaring above for `in PLACE BLOCK`)
+ // should go here, desugaring
+ //
+ // to:
+ //
+ // let mut place = BoxPlace::make_place();
+ // let raw_place = Place::pointer(&mut place);
+ // let value = $value;
+ // unsafe {
+ // ::std::ptr::write(raw_place, value);
+ // Boxed::finalize(place)
+ // }
+ //
+ // But for now there are type-inference issues doing that.
+ ExprBox(ref e) => {
+ hir::ExprBox(lower_expr(lctx, e))
+ }
+
+ // Desugar ExprBox: `in (PLACE) EXPR`
+ ExprInPlace(ref placer, ref value_expr) => {
+ // to:
+ //
+ // let p = PLACE;
+ // let mut place = Placer::make_place(p);
+ // let raw_place = Place::pointer(&mut place);
+ // push_unsafe!({
+ // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
+ // InPlace::finalize(place)
+ // })
+ let _old_cached = CachedIdSetter::new(lctx, e.id);
+
+ let placer_expr = lower_expr(lctx, placer);
+ let value_expr = lower_expr(lctx, value_expr);
+
+ let placer_ident = lctx.str_to_ident("placer");
+ let agent_ident = lctx.str_to_ident("place");
+ let p_ptr_ident = lctx.str_to_ident("p_ptr");
+
+ let make_place = ["ops", "Placer", "make_place"];
+ let place_pointer = ["ops", "Place", "pointer"];
+ let move_val_init = ["intrinsics", "move_val_init"];
+ let inplace_finalize = ["ops", "InPlace", "finalize"];
+
+ let make_call = |lctx, p, args| {
+ let path = core_path(lctx, e.span, p);
+ let path = expr_path(lctx, path);
+ expr_call(lctx, e.span, path, args)
+ };
+
+ let mk_stmt_let = |lctx, bind, expr| stmt_let(lctx, e.span, false, bind, expr);
+ let mk_stmt_let_mut = |lctx, bind, expr| stmt_let(lctx, e.span, true, bind, expr);
+
+ // let placer = <placer_expr> ;
+ let s1 = mk_stmt_let(lctx,
+ placer_ident,
+ signal_block_expr(lctx,
+ vec![],
+ placer_expr,
+ e.span,
+ hir::PopUnstableBlock));
+
+ // let mut place = Placer::make_place(placer);
+ let s2 = {
+ let call = make_call(lctx,
+ &make_place,
+ vec![expr_ident(lctx, e.span, placer_ident)]);
+ mk_stmt_let_mut(lctx, agent_ident, call)
+ };
+
+ // let p_ptr = Place::pointer(&mut place);
+ let s3 = {
+ let args = vec![expr_mut_addr_of(lctx,
+ e.span,
+ expr_ident(lctx, e.span, agent_ident))];
+ let call = make_call(lctx, &place_pointer, args);
+ mk_stmt_let(lctx, p_ptr_ident, call)
+ };
+
+ // pop_unsafe!(EXPR));
+ let pop_unsafe_expr =
+ signal_block_expr(lctx,
+ vec![],
+ signal_block_expr(lctx,
+ vec![],
+ value_expr,
+ e.span,
+ hir::PopUnstableBlock),
+ e.span,
+ hir::PopUnsafeBlock(hir::CompilerGenerated));
+
+ // push_unsafe!({
+ // std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
+ // InPlace::finalize(place)
+ // })
+ let expr = {
+ let call_move_val_init = hir::StmtSemi(make_call(lctx,
+ &move_val_init,
+ vec![expr_ident(lctx, e.span, p_ptr_ident),
+ pop_unsafe_expr]),
+ lctx.next_id());
+ let call_move_val_init = respan(e.span, call_move_val_init);
+
+ let call = make_call(lctx,
+ &inplace_finalize,
+ vec![expr_ident(lctx, e.span, agent_ident)]);
+ signal_block_expr(lctx,
+ vec![P(call_move_val_init)],
+ call,
+ e.span,
+ hir::PushUnsafeBlock(hir::CompilerGenerated))
+ };
+
+ return signal_block_expr(lctx,
+ vec![s1, s2, s3],
+ expr,
+ e.span,
+ hir::PushUnstableBlock);
+ }
+
+ ExprVec(ref exprs) => {
+ hir::ExprVec(exprs.iter().map(|x| lower_expr(lctx, x)).collect())
+ }
+ ExprRepeat(ref expr, ref count) => {
+ hir::ExprRepeat(lower_expr(lctx, expr), lower_expr(lctx, count))
+ }
+ ExprTup(ref elts) => {
+ hir::ExprTup(elts.iter().map(|x| lower_expr(lctx, x)).collect())
+ }
+ ExprCall(ref f, ref args) => {
+ hir::ExprCall(lower_expr(lctx, f),
+ args.iter().map(|x| lower_expr(lctx, x)).collect())
+ }
+ ExprMethodCall(i, ref tps, ref args) => {
+ hir::ExprMethodCall(respan(i.span, i.node.name),
+ tps.iter().map(|x| lower_ty(lctx, x)).collect(),
+ args.iter().map(|x| lower_expr(lctx, x)).collect())
+ }
+ ExprBinary(binop, ref lhs, ref rhs) => {
+ hir::ExprBinary(lower_binop(lctx, binop),
+ lower_expr(lctx, lhs),
+ lower_expr(lctx, rhs))
+ }
+ ExprUnary(op, ref ohs) => {
+ hir::ExprUnary(lower_unop(lctx, op), lower_expr(lctx, ohs))
+ }
+ ExprLit(ref l) => hir::ExprLit(P((**l).clone())),
+ ExprCast(ref expr, ref ty) => {
+ hir::ExprCast(lower_expr(lctx, expr), lower_ty(lctx, ty))
+ }
+ ExprAddrOf(m, ref ohs) => {
+ hir::ExprAddrOf(lower_mutability(lctx, m), lower_expr(lctx, ohs))
+ }
+ // More complicated than you might expect because the else branch
+ // might be `if let`.
+ ExprIf(ref cond, ref blk, ref else_opt) => {
+ let else_opt = else_opt.as_ref().map(|els| {
+ match els.node {
+ ExprIfLet(..) => {
+ let _old_cached = CachedIdSetter::new(lctx, e.id);
+ // wrap the if-let expr in a block
+ let span = els.span;
+ let blk = P(hir::Block {
+ stmts: vec![],
+ expr: Some(lower_expr(lctx, els)),
+ id: lctx.next_id(),
+ rules: hir::DefaultBlock,
+ span: span,
+ });
+ expr_block(lctx, blk)