Skip to content

Commit

Permalink
introduce Guard enum
Browse files Browse the repository at this point in the history
  • Loading branch information
F001 committed Aug 30, 2018
1 parent 70c33bb commit 7a083ca
Show file tree
Hide file tree
Showing 22 changed files with 115 additions and 35 deletions.
5 changes: 3 additions & 2 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,8 +488,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
// 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
Expand Down
6 changes: 5 additions & 1 deletion src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1102,7 +1102,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {

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);
}
Expand Down
5 changes: 4 additions & 1 deletion src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1053,7 +1053,10 @@ impl<'a> LoweringContext<'a> {
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)),
}
}
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1204,10 +1204,15 @@ impl DeclKind {
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,
Expand Down
12 changes: 8 additions & 4 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1951,10 +1951,14 @@ impl<'a> State<'a> {
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("=>")?;

Expand Down
4 changes: 4 additions & 0 deletions src/librustc/ich/impls_hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,10 @@ impl_stable_hash_for!(struct hir::Arm {
body
});

impl_stable_hash_for!(enum hir::Guard {
If(expr),
});

impl_stable_hash_for!(struct hir::Field {
id -> _,
ident,
Expand Down
4 changes: 3 additions & 1 deletion src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -792,7 +792,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
}

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);
Expand Down
7 changes: 6 additions & 1 deletion src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1028,7 +1028,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
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
Expand Down
6 changes: 4 additions & 2 deletions src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -884,8 +884,10 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
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);
Expand Down
6 changes: 4 additions & 2 deletions src/librustc_mir/build/matches/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ pub struct Candidate<'pat, 'tcx:'pat> {
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,
Expand Down Expand Up @@ -998,7 +998,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {

// 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 {
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_mir/hair/cx/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,10 @@ impl ToBorrowKind for hir::Mutability {
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,
Expand Down
7 changes: 6 additions & 1 deletion src/librustc_mir/hair/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,16 @@ pub struct FruInfo<'tcx> {
#[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,
Expand Down
17 changes: 13 additions & 4 deletions src/librustc_mir/hair/pattern/check_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
}
(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.
Expand Down Expand Up @@ -575,12 +577,19 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
/// 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> {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_passes/rvalue_promotion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ fn check_expr_kind<'a, 'tcx>(
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 => {},
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2691,7 +2691,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
// 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();
Expand Down
5 changes: 4 additions & 1 deletion src/librustc_save_analysis/dump_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1663,7 +1663,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc

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);
}

Expand Down
6 changes: 4 additions & 2 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,9 +663,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
};

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);
Expand Down
7 changes: 6 additions & 1 deletion src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -857,10 +857,15 @@ pub struct Local {
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,
Expand Down
12 changes: 11 additions & 1 deletion src/libsyntax/fold.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ pub trait Folder : Sized {
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)
}
Expand Down Expand Up @@ -353,11 +357,17 @@ pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm,
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),
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_target::spec::abi::{self, Abi};
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};
Expand Down Expand Up @@ -3509,7 +3509,7 @@ impl<'a> Parser<'a> {
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
};
Expand Down
12 changes: 8 additions & 4 deletions src/libsyntax/print/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2704,10 +2704,14 @@ impl<'a> State<'a> {
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("=>")?;

Expand Down
6 changes: 5 additions & 1 deletion src/libsyntax/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {

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);
}
Expand Down

0 comments on commit 7a083ca

Please sign in to comment.