Skip to content

refactor match guard #53815

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Sep 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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