Desugar 'if let' into the appropriate 'match'
This commit is contained in:
parent
5d8cfd53b5
commit
0e6ff432dc
@ -222,6 +222,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
self.add_node(expr.id, [then_exit, else_exit]) // 4, 5
|
||||
}
|
||||
|
||||
ast::ExprIfLet(..) => fail!("non-desugared ExprIfLet"),
|
||||
|
||||
ast::ExprWhile(ref cond, ref body, _) => {
|
||||
//
|
||||
// [pred]
|
||||
|
@ -374,6 +374,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> {
|
||||
}
|
||||
}
|
||||
|
||||
ast::ExprIfLet(..) => fail!("non-desugared ExprIfLet"),
|
||||
|
||||
ast::ExprMatch(ref discr, ref arms) => {
|
||||
let discr_cmt = return_if_err!(self.mc.cat_expr(&**discr));
|
||||
self.borrow_expr(&**discr, ty::ReEmpty, ty::ImmBorrow, MatchDiscriminant);
|
||||
|
@ -481,6 +481,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
|
||||
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
||||
visit::walk_expr(ir, expr);
|
||||
}
|
||||
ExprIfLet(..) => fail!("non-desugared ExprIfLet"),
|
||||
ExprForLoop(ref pat, _, _, _) => {
|
||||
pat_util::pat_bindings(&ir.tcx.def_map, &**pat, |bm, p_id, sp, path1| {
|
||||
debug!("adding local variable {} from for loop with bm {:?}",
|
||||
@ -1011,6 +1012,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
self.propagate_through_expr(&**cond, ln)
|
||||
}
|
||||
|
||||
ExprIfLet(..) => fail!("non-desugared ExprIfLet"),
|
||||
|
||||
ExprWhile(ref cond, ref blk, _) => {
|
||||
self.propagate_through_loop(expr, WhileLoop(&**cond), &**blk, succ)
|
||||
}
|
||||
@ -1470,6 +1473,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
||||
ExprPath(..) | ExprBox(..) => {
|
||||
visit::walk_expr(this, expr);
|
||||
}
|
||||
ExprIfLet(..) => fail!("non-desugared ExprIfLet")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -505,6 +505,8 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
|
||||
ast::ExprForLoop(..) => {
|
||||
Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty))
|
||||
}
|
||||
|
||||
ast::ExprIfLet(..) => fail!("non-desugared ExprIfLet")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3576,6 +3576,11 @@ fn populate_scope_map(cx: &CrateContext,
|
||||
}
|
||||
}
|
||||
|
||||
ast::ExprIfLet(..) => {
|
||||
cx.sess().span_bug(exp.span, "debuginfo::populate_scope_map() - \
|
||||
Found unexpanded if-let.");
|
||||
}
|
||||
|
||||
ast::ExprWhile(ref cond_exp, ref loop_body, _) => {
|
||||
walk_expr(cx, &**cond_exp, scope_stack, scope_map);
|
||||
|
||||
|
@ -3634,6 +3634,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
||||
ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
|
||||
RvalueDpsExpr
|
||||
}
|
||||
ast::ExprIfLet(..) => fail!("non-desugared ExprIfLet"),
|
||||
|
||||
ast::ExprCast(..) => {
|
||||
match tcx.node_types.borrow().find(&(expr.id as uint)) {
|
||||
|
@ -4106,6 +4106,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
||||
check_then_else(fcx, &**cond, &**then_blk, opt_else_expr.as_ref().map(|e| &**e),
|
||||
id, expr.span, expected);
|
||||
}
|
||||
ast::ExprIfLet(..) => fail!("non-desugared ExprIfLet"),
|
||||
ast::ExprWhile(ref cond, ref body, _) => {
|
||||
check_expr_has_type(fcx, &**cond, ty::mk_bool());
|
||||
check_block_no_value(fcx, &**body);
|
||||
|
@ -293,6 +293,7 @@ mod svh_visitor {
|
||||
ExprForLoop(..) => SawExprForLoop,
|
||||
|
||||
// just syntactic artifacts, expanded away by time of SVH.
|
||||
ExprIfLet(..) => unreachable!(),
|
||||
ExprMac(..) => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
|
||||
e.and_then(|ast::Expr {id, node, span}| match node {
|
||||
// expr_mac should really be expr_ext or something; it's the
|
||||
// entry-point for all syntax extensions.
|
||||
ExprMac(mac) => {
|
||||
ast::ExprMac(mac) => {
|
||||
let expanded_expr = match expand_mac_invoc(mac, span,
|
||||
|r| r.make_expr(),
|
||||
mark_expr, fld) {
|
||||
@ -67,6 +67,95 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
|
||||
fld.cx.expr(span, ast::ExprWhile(cond, body, opt_ident))
|
||||
}
|
||||
|
||||
// Desugar ExprIfLet
|
||||
// From: `if let <pat> = <expr> <body> [<elseopt>]`
|
||||
ast::ExprIfLet(pat, expr, body, mut elseopt) => {
|
||||
let span = e.span;
|
||||
|
||||
// to:
|
||||
//
|
||||
// match <expr> {
|
||||
// <pat> => <body>,
|
||||
// [_ if <elseopt_if_cond> => <elseopt_if_body>,]
|
||||
// _ => [<elseopt> | ()]
|
||||
// }
|
||||
|
||||
// `<pat> => <body>`
|
||||
let pat_arm = {
|
||||
let body_expr = fld.cx.expr_block(body);
|
||||
fld.cx.arm(pat.span, vec![pat], body_expr)
|
||||
};
|
||||
|
||||
// `[_ if <elseopt_if_cond> => <elseopt_if_body>,]`
|
||||
let else_if_arms = {
|
||||
let mut arms = vec![];
|
||||
loop {
|
||||
// NOTE: replace with 'if let' after snapshot
|
||||
match elseopt {
|
||||
Some(els) => match els.node {
|
||||
// else if
|
||||
ast::ExprIf(cond, then, elseopt_) => {
|
||||
let pat_under = fld.cx.pat_wild(span);
|
||||
elseopt = elseopt_;
|
||||
arms.push(ast::Arm {
|
||||
attrs: vec![],
|
||||
pats: vec![pat_under],
|
||||
guard: Some(cond),
|
||||
body: fld.cx.expr_block(then)
|
||||
});
|
||||
}
|
||||
_ => break
|
||||
},
|
||||
None => break
|
||||
}
|
||||
}
|
||||
arms
|
||||
};
|
||||
|
||||
// `_ => [<elseopt> | ()]`
|
||||
let else_arm = {
|
||||
let pat_under = fld.cx.pat_wild(span);
|
||||
let else_expr = match elseopt {
|
||||
Some(els) => els,
|
||||
None => fld.cx.expr_lit(span, ast::LitNil)
|
||||
};
|
||||
fld.cx.arm(span, vec![pat_under], else_expr)
|
||||
};
|
||||
|
||||
let mut arms = Vec::with_capacity(else_if_arms.len() + 2);
|
||||
arms.push(pat_arm);
|
||||
arms.push_all_move(else_if_arms);
|
||||
arms.push(else_arm);
|
||||
|
||||
let match_expr = fld.cx.expr_match(span, expr, arms);
|
||||
fld.fold_expr(match_expr)
|
||||
}
|
||||
|
||||
// Desugar support for ExprIfLet in the ExprIf else position
|
||||
ast::ExprIf(cond, blk, mut elseopt) => {
|
||||
// NOTE: replace with 'if let' after snapshot
|
||||
match elseopt {
|
||||
Some(els) => match els.node {
|
||||
ast::ExprIfLet(..) => {
|
||||
// wrap the if-let expr in a block
|
||||
let blk = P(ast::Block {
|
||||
view_items: vec![],
|
||||
stmts: vec![],
|
||||
expr: Some(els),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
rules: ast::DefaultBlock,
|
||||
span: els.span
|
||||
});
|
||||
elseopt = Some(fld.cx.expr_block(blk));
|
||||
}
|
||||
_ => ()
|
||||
},
|
||||
None => ()
|
||||
};
|
||||
let if_expr = fld.cx.expr(e.span, ast::ExprIf(cond, blk, elseopt));
|
||||
noop_fold_expr(if_expr, fld)
|
||||
}
|
||||
|
||||
ast::ExprLoop(loop_block, opt_ident) => {
|
||||
let (loop_block, opt_ident) = expand_loop_block(loop_block, opt_ident, fld);
|
||||
fld.cx.expr(span, ast::ExprLoop(loop_block, opt_ident))
|
||||
|
Loading…
x
Reference in New Issue
Block a user