Skip to content

Commit 28bcffe

Browse files
committed
Auto merge of #53815 - F001:if-let-guard, r=petrochenkov
refactor match guard This is the first step to implement RFC 2294: if-let-guard. Tracking issue: #51114 The second step should be introducing another variant `IfLet` in the Guard enum. I separated them into 2 PRs for the convenience of reviewers. r? @petrochenkov
2 parents f39f218 + 7a083ca commit 28bcffe

File tree

22 files changed

+115
-35
lines changed

22 files changed

+115
-35
lines changed

src/librustc/cfg/construct.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -488,8 +488,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
488488
// expression to target
489489
let guard_start = self.add_dummy_node(&[pat_exit]);
490490
// Visit the guard expression
491-
let guard_exit = self.expr(&guard, guard_start);
492-
491+
let guard_exit = match guard {
492+
hir::Guard::If(ref e) => self.expr(e, guard_start),
493+
};
493494
// #47295: We used to have very special case code
494495
// here for when a pair of arms are both formed
495496
// solely from constants, and if so, not add these

src/librustc/hir/intravisit.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,11 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
11021102

11031103
pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm) {
11041104
walk_list!(visitor, visit_pat, &arm.pats);
1105-
walk_list!(visitor, visit_expr, &arm.guard);
1105+
if let Some(ref g) = arm.guard {
1106+
match g {
1107+
Guard::If(ref e) => visitor.visit_expr(e),
1108+
}
1109+
}
11061110
visitor.visit_expr(&arm.body);
11071111
walk_list!(visitor, visit_attribute, &arm.attrs);
11081112
}

src/librustc/hir/lowering.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,10 @@ impl<'a> LoweringContext<'a> {
10541054
hir::Arm {
10551055
attrs: self.lower_attrs(&arm.attrs),
10561056
pats: arm.pats.iter().map(|x| self.lower_pat(x)).collect(),
1057-
guard: arm.guard.as_ref().map(|ref x| P(self.lower_expr(x))),
1057+
guard: match arm.guard {
1058+
Some(Guard::If(ref x)) => Some(hir::Guard::If(P(self.lower_expr(x)))),
1059+
_ => None,
1060+
},
10581061
body: P(self.lower_expr(&arm.body)),
10591062
}
10601063
}

src/librustc/hir/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1204,10 +1204,15 @@ impl DeclKind {
12041204
pub struct Arm {
12051205
pub attrs: HirVec<Attribute>,
12061206
pub pats: HirVec<P<Pat>>,
1207-
pub guard: Option<P<Expr>>,
1207+
pub guard: Option<Guard>,
12081208
pub body: P<Expr>,
12091209
}
12101210

1211+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1212+
pub enum Guard {
1213+
If(P<Expr>),
1214+
}
1215+
12111216
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
12121217
pub struct Field {
12131218
pub id: NodeId,

src/librustc/hir/print.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1949,10 +1949,14 @@ impl<'a> State<'a> {
19491949
self.print_pat(&p)?;
19501950
}
19511951
self.s.space()?;
1952-
if let Some(ref e) = arm.guard {
1953-
self.word_space("if")?;
1954-
self.print_expr(&e)?;
1955-
self.s.space()?;
1952+
if let Some(ref g) = arm.guard {
1953+
match g {
1954+
hir::Guard::If(e) => {
1955+
self.word_space("if")?;
1956+
self.print_expr(&e)?;
1957+
self.s.space()?;
1958+
}
1959+
}
19561960
}
19571961
self.word_space("=>")?;
19581962

src/librustc/ich/impls_hir.rs

+4
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,10 @@ impl_stable_hash_for!(struct hir::Arm {
493493
body
494494
});
495495

496+
impl_stable_hash_for!(enum hir::Guard {
497+
If(expr),
498+
});
499+
496500
impl_stable_hash_for!(struct hir::Field {
497501
id -> _,
498502
ident,

src/librustc/middle/expr_use_visitor.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
792792
}
793793

794794
if let Some(ref guard) = arm.guard {
795-
self.consume_expr(&guard);
795+
match guard {
796+
hir::Guard::If(ref e) => self.consume_expr(e),
797+
}
796798
}
797799

798800
self.consume_expr(&arm.body);

src/librustc/middle/liveness.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
10301030
let body_succ =
10311031
self.propagate_through_expr(&arm.body, succ);
10321032
let guard_succ =
1033-
self.propagate_through_opt_expr(arm.guard.as_ref().map(|e| &**e), body_succ);
1033+
self.propagate_through_opt_expr(
1034+
arm.guard.as_ref().map(|g|
1035+
match g {
1036+
hir::Guard::If(e) => &**e,
1037+
}),
1038+
body_succ);
10341039
// only consider the first pattern; any later patterns must have
10351040
// the same bindings, and we also consider the first pattern to be
10361041
// the "authoritative" set of ids

src/librustc/middle/region.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -885,8 +885,10 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk:
885885
fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) {
886886
visitor.terminating_scopes.insert(arm.body.hir_id.local_id);
887887

888-
if let Some(ref expr) = arm.guard {
889-
visitor.terminating_scopes.insert(expr.hir_id.local_id);
888+
if let Some(ref g) = arm.guard {
889+
match g {
890+
hir::Guard::If(ref expr) => visitor.terminating_scopes.insert(expr.hir_id.local_id),
891+
};
890892
}
891893

892894
intravisit::walk_arm(visitor, arm);

src/librustc_mir/build/matches/mod.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ pub struct Candidate<'pat, 'tcx:'pat> {
453453
bindings: Vec<Binding<'tcx>>,
454454

455455
// ...and the guard must be evaluated...
456-
guard: Option<ExprRef<'tcx>>,
456+
guard: Option<Guard<'tcx>>,
457457

458458
// ...and then we branch to arm with this index.
459459
arm_index: usize,
@@ -998,7 +998,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
998998

999999
// the block to branch to if the guard fails; if there is no
10001000
// guard, this block is simply unreachable
1001-
let guard = self.hir.mirror(guard);
1001+
let guard = match guard {
1002+
Guard::If(e) => self.hir.mirror(e),
1003+
};
10021004
let source_info = self.source_info(guard.span);
10031005
let cond = unpack!(block = self.as_local_operand(block, guard));
10041006
if autoref {

src/librustc_mir/hair/cx/expr.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,10 @@ impl ToBorrowKind for hir::Mutability {
837837
fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
838838
Arm {
839839
patterns: arm.pats.iter().map(|p| cx.pattern_from_hir(p)).collect(),
840-
guard: arm.guard.to_ref(),
840+
guard: match arm.guard {
841+
Some(hir::Guard::If(ref e)) => Some(Guard::If(e.to_ref())),
842+
_ => None,
843+
},
841844
body: arm.body.to_ref(),
842845
// BUG: fix this
843846
lint_level: LintLevel::Inherited,

src/librustc_mir/hair/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -316,11 +316,16 @@ pub struct FruInfo<'tcx> {
316316
#[derive(Clone, Debug)]
317317
pub struct Arm<'tcx> {
318318
pub patterns: Vec<Pattern<'tcx>>,
319-
pub guard: Option<ExprRef<'tcx>>,
319+
pub guard: Option<Guard<'tcx>>,
320320
pub body: ExprRef<'tcx>,
321321
pub lint_level: LintLevel,
322322
}
323323

324+
#[derive(Clone, Debug)]
325+
pub enum Guard<'tcx> {
326+
If(ExprRef<'tcx>),
327+
}
328+
324329
#[derive(Copy, Clone, Debug)]
325330
pub enum LogicalOp {
326331
And,

src/librustc_mir/hair/pattern/check_match.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
208208
}
209209
(pattern, &**pat)
210210
}).collect(),
211-
arm.guard.as_ref().map(|e| &**e)
211+
arm.guard.as_ref().map(|g| match g {
212+
hir::Guard::If(ref e) => &**e,
213+
})
212214
)).collect();
213215

214216
// Bail out early if inlining failed.
@@ -575,12 +577,19 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
575577
/// assign.
576578
///
577579
/// FIXME: this should be done by borrowck.
578-
fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Expr) {
580+
fn check_for_mutation_in_guard(cx: &MatchVisitor, guard: &hir::Guard) {
579581
let mut checker = MutationChecker {
580582
cx,
581583
};
582-
ExprUseVisitor::new(&mut checker, cx.tcx, cx.param_env, cx.region_scope_tree, cx.tables, None)
583-
.walk_expr(guard);
584+
match guard {
585+
hir::Guard::If(expr) =>
586+
ExprUseVisitor::new(&mut checker,
587+
cx.tcx,
588+
cx.param_env,
589+
cx.region_scope_tree,
590+
cx.tables,
591+
None).walk_expr(expr),
592+
};
584593
}
585594

586595
struct MutationChecker<'a, 'tcx: 'a> {

src/librustc_passes/rvalue_promotion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,7 @@ fn check_expr_kind<'a, 'tcx>(
577577
for index in hirvec_arm.iter() {
578578
let _ = v.check_expr(&*index.body);
579579
match index.guard {
580-
Some(ref expr) => {
580+
Some(hir::Guard::If(ref expr)) => {
581581
let _ = v.check_expr(&expr);
582582
},
583583
None => {},

src/librustc_resolve/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2701,7 +2701,10 @@ impl<'a, 'crateloader: 'a> Resolver<'a, 'crateloader> {
27012701
// This has to happen *after* we determine which pat_idents are variants
27022702
self.check_consistent_bindings(&arm.pats);
27032703

2704-
walk_list!(self, visit_expr, &arm.guard);
2704+
match arm.guard {
2705+
Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
2706+
_ => {}
2707+
}
27052708
self.visit_expr(&arm.body);
27062709

27072710
self.ribs[ValueNS].pop();

src/librustc_save_analysis/dump_visitor.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1663,7 +1663,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> Visitor<'l> for DumpVisitor<'l, 'tc
16631663

16641664
fn visit_arm(&mut self, arm: &'l ast::Arm) {
16651665
self.process_var_decl_multi(&arm.pats);
1666-
walk_list!(self, visit_expr, &arm.guard);
1666+
match arm.guard {
1667+
Some(ast::Guard::If(ref expr)) => self.visit_expr(expr),
1668+
_ => {}
1669+
}
16671670
self.visit_expr(&arm.body);
16681671
}
16691672

src/librustc_typeck/check/_match.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -663,9 +663,11 @@ https://doc.rust-lang.org/reference/types.html#trait-objects");
663663
};
664664

665665
for (i, (arm, pats_diverge)) in arms.iter().zip(all_arm_pats_diverge).enumerate() {
666-
if let Some(ref e) = arm.guard {
666+
if let Some(ref g) = arm.guard {
667667
self.diverges.set(pats_diverge);
668-
self.check_expr_has_type_or_error(e, tcx.types.bool);
668+
match g {
669+
hir::Guard::If(e) => self.check_expr_has_type_or_error(e, tcx.types.bool),
670+
};
669671
}
670672

671673
self.diverges.set(pats_diverge);

src/libsyntax/ast.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -857,10 +857,15 @@ pub struct Local {
857857
pub struct Arm {
858858
pub attrs: Vec<Attribute>,
859859
pub pats: Vec<P<Pat>>,
860-
pub guard: Option<P<Expr>>,
860+
pub guard: Option<Guard>,
861861
pub body: P<Expr>,
862862
}
863863

864+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
865+
pub enum Guard {
866+
If(P<Expr>),
867+
}
868+
864869
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
865870
pub struct Field {
866871
pub ident: Ident,

src/libsyntax/fold.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ pub trait Folder : Sized {
118118
noop_fold_arm(a, self)
119119
}
120120

121+
fn fold_guard(&mut self, g: Guard) -> Guard {
122+
noop_fold_guard(g, self)
123+
}
124+
121125
fn fold_pat(&mut self, p: P<Pat>) -> P<Pat> {
122126
noop_fold_pat(p, self)
123127
}
@@ -354,11 +358,17 @@ pub fn noop_fold_arm<T: Folder>(Arm {attrs, pats, guard, body}: Arm,
354358
Arm {
355359
attrs: fold_attrs(attrs, fld),
356360
pats: pats.move_map(|x| fld.fold_pat(x)),
357-
guard: guard.map(|x| fld.fold_expr(x)),
361+
guard: guard.map(|x| fld.fold_guard(x)),
358362
body: fld.fold_expr(body),
359363
}
360364
}
361365

366+
pub fn noop_fold_guard<T: Folder>(g: Guard, fld: &mut T) -> Guard {
367+
match g {
368+
Guard::If(e) => Guard::If(fld.fold_expr(e)),
369+
}
370+
}
371+
362372
pub fn noop_fold_ty_binding<T: Folder>(b: TypeBinding, fld: &mut T) -> TypeBinding {
363373
TypeBinding {
364374
id: fld.new_id(b.id),

src/libsyntax/parse/parser.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_target::spec::abi::{self, Abi};
1212
use ast::{AngleBracketedArgs, ParenthesisedArgs, AttrStyle, BareFnTy};
1313
use ast::{GenericBound, TraitBoundModifier};
1414
use ast::Unsafety;
15-
use ast::{Mod, AnonConst, Arg, Arm, Attribute, BindingMode, TraitItemKind};
15+
use ast::{Mod, AnonConst, Arg, Arm, Guard, Attribute, BindingMode, TraitItemKind};
1616
use ast::Block;
1717
use ast::{BlockCheckMode, CaptureBy, Movability};
1818
use ast::{Constness, Crate};
@@ -3533,7 +3533,7 @@ impl<'a> Parser<'a> {
35333533
self.eat(&token::BinOp(token::Or));
35343534
let pats = self.parse_pats()?;
35353535
let guard = if self.eat_keyword(keywords::If) {
3536-
Some(self.parse_expr()?)
3536+
Some(Guard::If(self.parse_expr()?))
35373537
} else {
35383538
None
35393539
};

src/libsyntax/print/pprust.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -2702,10 +2702,14 @@ impl<'a> State<'a> {
27022702
self.print_outer_attributes(&arm.attrs)?;
27032703
self.print_pats(&arm.pats)?;
27042704
self.s.space()?;
2705-
if let Some(ref e) = arm.guard {
2706-
self.word_space("if")?;
2707-
self.print_expr(e)?;
2708-
self.s.space()?;
2705+
if let Some(ref g) = arm.guard {
2706+
match g {
2707+
ast::Guard::If(ref e) => {
2708+
self.word_space("if")?;
2709+
self.print_expr(e)?;
2710+
self.s.space()?;
2711+
}
2712+
}
27092713
}
27102714
self.word_space("=>")?;
27112715

src/libsyntax/visit.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,11 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
819819

820820
pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
821821
walk_list!(visitor, visit_pat, &arm.pats);
822-
walk_list!(visitor, visit_expr, &arm.guard);
822+
if let Some(ref g) = &arm.guard {
823+
match g {
824+
Guard::If(ref e) => visitor.visit_expr(e),
825+
}
826+
}
823827
visitor.visit_expr(&arm.body);
824828
walk_list!(visitor, visit_attribute, &arm.attrs);
825829
}

0 commit comments

Comments
 (0)