// expression to target
let guard_start = self.add_dummy_node(&[pat_exit]);
// Visit the guard expression
- let guard_exit = self.expr(&guard, guard_start);
-
+ let guard_exit = match guard {
+ hir::Guard::If(ref e) => self.expr(e, guard_start),
+ };
// #47295: We used to have very special case code
// here for when a pair of arms are both formed
// solely from constants, and if so, not add these
pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
walk_list!(visitor, visit_pat, &arm.pats);
- walk_list!(visitor, visit_expr, &arm.guard);
+ if let Some(ref g) = arm.guard {
+ match g {
+ Guard::If(ref e) => visitor.visit_expr(e),
+ }
+ }
visitor.visit_expr(&arm.body);
walk_list!(visitor, visit_attribute, &arm.attrs);
}
hir::Arm {
attrs: self.lower_attrs(&arm.attrs),
pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
- guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))),
+ guard: match arm.guard {
+ Some(Guard::If(ref x)) => Some(hir::Guard::If(P(self.lower_expr(x)))),
+ _ => None,
+ },
body: P(self.lower_expr(&arm.body)),
}
}
pub struct Arm {
pub attrs: HirVec<Attribute>,
pub pats: HirVec<P<Pat>>,
- pub guard: Option<P<Expr>>,
+ pub guard: Option<Guard>,
pub body: P<Expr>,
}
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum Guard {
+ If(P<Expr>),
+}
+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Field {
pub id: NodeId,
self.print_pat(&p)?;
}
self.s.space()?;
- if let Some(ref e) = arm.guard {
- self.word_space("if")?;
- self.print_expr(&e)?;
- self.s.space()?;
+ if let Some(ref g) = arm.guard {
+ match g {
+ hir::Guard::If(e) => {
+ self.word_space("if")?;
+ self.print_expr(&e)?;
+ self.s.space()?;
+ }
+ }
}
self.word_space("=>")?;
body
});
+impl_stable_hash_for!(enum hir::Guard {
+ If(expr),
+});
+
impl_stable_hash_for!(struct hir::Field {
id -> _,
ident,
}
if let Some(ref guard) = arm.guard {
- self.consume_expr(&guard);
+ match guard {
+ hir::Guard::If(ref e) => self.consume_expr(e),
+ }
}
self.consume_expr(&arm.body);
let body_succ =
self.propagate_through_expr(&arm.body, succ);
let guard_succ =
- self.propagate_through_opt_expr(arm.guard.as_ref().map(|e| &**e), body_succ);
+ self.propagate_through_opt_expr(
+ arm.guard.as_ref().map(|g|
+ match g {
+ hir::Guard::If(e) => &**e,
+ }),
+ body_succ);
// only consider the first pattern; any later patterns must have
// the same bindings, and we also consider the first pattern to be
// the "authoritative" set of ids
fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) {
visitor.terminating_scopes.insert(arm.body.hir_id.local_id);
- if let Some(ref expr) = arm.guard {
- visitor.terminating_scopes.insert(expr.hir_id.local_id);
+ if let Some(ref g) = arm.guard {
+ match g {
+ hir::Guard::If(ref expr) => visitor.terminating_scopes.insert(expr.hir_id.local_id),
+ };
}
intravisit::walk_arm(visitor, arm);
bindings: Vec<Binding<'tcx>>,
// ...and the guard must be evaluated...
- guard: Option<ExprRef<'tcx>>,
+ guard: Option<Guard<'tcx>>,
// ...and then we branch to arm with this index.
arm_index: usize,
// the block to branch to if the guard fails; if there is no
// guard, this block is simply unreachable
- let guard = self.hir.mirror(guard);
+ let guard = match guard {
+ Guard::If(e) => self.hir.mirror(e),
+ };
let source_info = self.source_info(guard.span);
let cond = unpack!(block = self.as_local_operand(block, guard));
if autoref {
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
Arm {
patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
- guard: arm.guard.to_ref(),
+ guard: match arm.guard {
+ Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())),
+ _ => None,
+ },
body: arm.body.to_ref(),
// BUG: fix this
lint_level: LintLevel::Inherited,
#[derive(Clone, Debug)]
pub struct Arm<'tcx> {
pub patterns: Vec<Pattern<'tcx>>,
- pub guard: Option<ExprRef<'tcx>>,
+ pub guard: Option<Guard<'tcx>>,
pub body: ExprRef<'tcx>,
pub lint_level: LintLevel,
}
+#[derive(Clone, Debug)]
+pub enum Guard<'tcx> {
+ If(ExprRef<'tcx>),
+}
+
#[derive(Copy, Clone, Debug)]
pub enum LogicalOp {
And,
}
(pattern, &**pat)
}).collect(),
- arm.guard.as_ref().map(|e| &**e)
+ arm.guard.as_ref().map(|g| match g {
+ hir::Guard::If(ref e) => &**e,
+ })
)).collect();
// Bail out early if inlining failed.
/// assign.
///
/// FIXME: this should be done by borrowck.
-fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
+fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Guard) {
let mut checker = MutationChecker {
cx,
};
- ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables, None)
- .walk_expr(guard);
+ match guard {
+ hir::Guard::If(expr) =>
+ ExprUseVisitor::new(&mut checker,
+ cx.tcx,
+ cx.param_env,
+ cx.region_scope_tree,
+ cx.tables,
+ None).walk_expr(expr),
+ };
}
struct MutationChecker<'a, 'tcx: 'a> {
for index in hirvec_arm.iter() {
let _ = v.check_expr(&*index.body);
match index.guard {
- Some(ref expr) => {
+ Some(hir::Guard::If(ref expr)) => {
let _ = v.check_expr(&expr);
},
None => {},
// This has to happen *after* we determine which pat_idents are variants
self.check_consistent_bindings(&arm.pats);
- walk_list!(self, visit_expr, &arm.guard);
+ match arm.guard {
+ Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
+ _ => {}
+ }
self.visit_expr(&arm.body);
self.ribs[ValueNS].pop();
fn visit_arm(&mut self, arm: &'l ast::Arm) {
self.process_var_decl_multi(&arm.pats);
- walk_list!(self, visit_expr, &arm.guard);
+ match arm.guard {
+ Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
+ _ => {}
+ }
self.visit_expr(&arm.body);
}
};
for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
- if let Some(ref e) = arm.guard {
+ if let Some(ref g) = arm.guard {
self.diverges.set(pats_diverge);
- self.check_expr_has_type_or_error(e, tcx.types.bool);
+ match g {
+ hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
+ };
}
self.diverges.set(pats_diverge);
pub struct Arm {
pub attrs: Vec<Attribute>,
pub pats: Vec<P<Pat>>,
- pub guard: Option<P<Expr>>,
+ pub guard: Option<Guard>,
pub body: P<Expr>,
}
+#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
+pub enum Guard {
+ If(P<Expr>),
+}
+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Field {
pub ident: Ident,
noop_fold_arm(a, self)
}
+ fn fold_guard(&mut self, g: Guard) -> Guard {
+ noop_fold_guard(g, self)
+ }
+
fn fold_pat(&mut self, p: P<Pat>) -> P<Pat> {
noop_fold_pat(p, self)
}
Arm {
attrs: fold_attrs(attrs, fld),
pats: pats.move_map(|x| fld.fold_pat(x)),
- guard: guard.map(|x| fld.fold_expr(x)),
+ guard: guard.map(|x| fld.fold_guard(x)),
body: fld.fold_expr(body),
}
}
+pub fn noop_fold_guard<T: Folder>(g: Guard, fld: &mut T) -> Guard {
+ match g {
+ Guard::If(e) => Guard::If(fld.fold_expr(e)),
+ }
+}
+
pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBinding {
TypeBinding {
id: fld.new_id(b.id),
use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy};
use ast::{GenericBound, TraitBoundModifier};
use ast::Unsafety;
-use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind};
+use ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
use ast::Block;
use ast::{BlockCheckMode, CaptureBy, Movability};
use ast::{Constness, Crate};
self.eat(&token::BinOp(token::Or));
let pats = self.parse_pats()?;
let guard = if self.eat_keyword(keywords::If) {
- Some(self.parse_expr()?)
+ Some(Guard::If(self.parse_expr()?))
} else {
None
};
self.print_outer_attributes(&arm.attrs)?;
self.print_pats(&arm.pats)?;
self.s.space()?;
- if let Some(ref e) = arm.guard {
- self.word_space("if")?;
- self.print_expr(e)?;
- self.s.space()?;
+ if let Some(ref g) = arm.guard {
+ match g {
+ ast::Guard::If(ref e) => {
+ self.word_space("if")?;
+ self.print_expr(e)?;
+ self.s.space()?;
+ }
+ }
}
self.word_space("=>")?;
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
walk_list!(visitor, visit_pat, &arm.pats);
- walk_list!(visitor, visit_expr, &arm.guard);
+ if let Some(ref g) = &arm.guard {
+ match g {
+ Guard::If(ref e) => visitor.visit_expr(e),
+ }
+ }
visitor.visit_expr(&arm.body);
walk_list!(visitor, visit_attribute, &arm.attrs);
}