From 7a083ca25f14833d704d2efba5ca9b431f6c65ad Mon Sep 17 00:00:00 2001 From: F001 Date: Thu, 30 Aug 2018 12:18:11 +0800 Subject: [PATCH] introduce Guard enum --- src/librustc/cfg/construct.rs | 5 +++-- src/librustc/hir/intravisit.rs | 6 +++++- src/librustc/hir/lowering.rs | 5 ++++- src/librustc/hir/mod.rs | 7 ++++++- src/librustc/hir/print.rs | 12 ++++++++---- src/librustc/ich/impls_hir.rs | 4 ++++ src/librustc/middle/expr_use_visitor.rs | 4 +++- src/librustc/middle/liveness.rs | 7 ++++++- src/librustc/middle/region.rs | 6 ++++-- src/librustc_mir/build/matches/mod.rs | 6 ++++-- src/librustc_mir/hair/cx/expr.rs | 5 ++++- src/librustc_mir/hair/mod.rs | 7 ++++++- src/librustc_mir/hair/pattern/check_match.rs | 17 +++++++++++++---- src/librustc_passes/rvalue_promotion.rs | 2 +- src/librustc_resolve/lib.rs | 5 ++++- src/librustc_save_analysis/dump_visitor.rs | 5 ++++- src/librustc_typeck/check/_match.rs | 6 ++++-- src/libsyntax/ast.rs | 7 ++++++- src/libsyntax/fold.rs | 12 +++++++++++- src/libsyntax/parse/parser.rs | 4 ++-- src/libsyntax/print/pprust.rs | 12 ++++++++---- src/libsyntax/visit.rs | 6 +++++- 22 files changed, 115 insertions(+), 35 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 98cfa094c16..1b974809203 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -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 diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index d853d3d9a7f..8129cc18d46 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -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); } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index b5f5f4d5c11..bb4fabf1c3e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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)), } } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 43cc33f422f..a4806502ab3 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1204,10 +1204,15 @@ impl DeclKind { pub struct Arm { pub attrs: HirVec, pub pats: HirVec>, - pub guard: Option>, + pub guard: Option, pub body: P, } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum Guard { + If(P), +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Field { pub id: NodeId, diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 9fe462e65a2..193fff1f5b6 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -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("=>")?; diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 76e57558bfe..c780ede75a4 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -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, diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 5beafe2b601..705237aa832 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -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); diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index 7d9590ee578..9850e2e8b1c 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -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 diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index be1d93dbad1..5302bc806c7 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -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); diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index b317bb7cff0..d3e67ea7b7d 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -453,7 +453,7 @@ pub struct Candidate<'pat, 'tcx:'pat> { bindings: Vec>, // ...and the guard must be evaluated... - guard: Option>, + guard: Option>, // ...and then we branch to arm with this index. arm_index: usize, @@ -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 { diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index b60da286d95..d90e9ed329b 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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, diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index c39aa9ca780..ab272763d8e 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -304,11 +304,16 @@ pub struct FruInfo<'tcx> { #[derive(Clone, Debug)] pub struct Arm<'tcx> { pub patterns: Vec>, - pub guard: Option>, + pub guard: Option>, 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, diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 35f9dcee99f..986bbced020 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -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. @@ -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> { diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs index 114fd8754a2..864d9e1a16f 100644 --- a/src/librustc_passes/rvalue_promotion.rs +++ b/src/librustc_passes/rvalue_promotion.rs @@ -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 => {}, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 71a7fde2029..96df0cbfc07 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -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(); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index dc9310cdcda..565986066da 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -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); } diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index c14a07b7cf5..d8c090dd6a7 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -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); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ec6ac86ba6b..63aaa487bf8 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -857,10 +857,15 @@ pub struct Local { pub struct Arm { pub attrs: Vec, pub pats: Vec>, - pub guard: Option>, + pub guard: Option, pub body: P, } +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum Guard { + If(P), +} + #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Field { pub ident: Ident, diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index 50a49e2f548..82dae3bc973 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -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) -> P { noop_fold_pat(p, self) } @@ -353,11 +357,17 @@ pub fn noop_fold_arm(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(g: Guard, fld: &mut T) -> Guard { + match g { + Guard::If(e) => Guard::If(fld.fold_expr(e)), + } +} + pub fn noop_fold_ty_binding(b: TypeBinding, fld: &mut T) -> TypeBinding { TypeBinding { id: fld.new_id(b.id), diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index b1e2e69863d..ceef03bb653 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -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}; @@ -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 }; diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3065e795ed8..da3ba928eff 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -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("=>")?; diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 51be129737e..fccc80b668f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -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); }