Skip to content

Commit a99376b

Browse files
authored
Rollup merge of rust-lang#119554 - matthewjasper:remove-guard-distinction, r=compiler-errors
Fix scoping for let chains in match guards If let guards were previously represented as a different type of guard in HIR and THIR. This meant that let chains in match guards were not handled correctly because they were treated exactly like normal guards. - Remove `hir::Guard` and `thir::Guard`. - Make the scoping different between normal guards and if let guards also check for let chains. closes rust-lang#118593
2 parents 45dd8c1 + 44bba54 commit a99376b

File tree

34 files changed

+272
-292
lines changed

34 files changed

+272
-292
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+1-14
Original file line numberDiff line numberDiff line change
@@ -546,20 +546,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
546546

547547
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
548548
let pat = self.lower_pat(&arm.pat);
549-
let guard = arm.guard.as_ref().map(|cond| {
550-
if let ExprKind::Let(pat, scrutinee, span, is_recovered) = &cond.kind {
551-
hir::Guard::IfLet(self.arena.alloc(hir::Let {
552-
hir_id: self.next_id(),
553-
span: self.lower_span(*span),
554-
pat: self.lower_pat(pat),
555-
ty: None,
556-
init: self.lower_expr(scrutinee),
557-
is_recovered: *is_recovered,
558-
}))
559-
} else {
560-
hir::Guard::If(self.lower_expr(cond))
561-
}
562-
});
549+
let guard = arm.guard.as_ref().map(|cond| self.lower_expr(cond));
563550
let hir_id = self.next_id();
564551
let span = self.lower_span(arm.span);
565552
self.lower_attrs(hir_id, &arm.attrs);

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3590,7 +3590,7 @@ impl<'b, 'v> Visitor<'v> for ConditionVisitor<'b> {
35903590
));
35913591
} else if let Some(guard) = &arm.guard {
35923592
self.errors.push((
3593-
arm.pat.span.to(guard.body().span),
3593+
arm.pat.span.to(guard.span),
35943594
format!(
35953595
"if this pattern and condition are matched, {} is not \
35963596
initialized",

compiler/rustc_hir/src/hir.rs

+1-21
Original file line numberDiff line numberDiff line change
@@ -1258,7 +1258,7 @@ pub struct Arm<'hir> {
12581258
/// If this pattern and the optional guard matches, then `body` is evaluated.
12591259
pub pat: &'hir Pat<'hir>,
12601260
/// Optional guard clause.
1261-
pub guard: Option<Guard<'hir>>,
1261+
pub guard: Option<&'hir Expr<'hir>>,
12621262
/// The expression the arm evaluates to if this arm matches.
12631263
pub body: &'hir Expr<'hir>,
12641264
}
@@ -1280,26 +1280,6 @@ pub struct Let<'hir> {
12801280
pub is_recovered: Option<ErrorGuaranteed>,
12811281
}
12821282

1283-
#[derive(Debug, Clone, Copy, HashStable_Generic)]
1284-
pub enum Guard<'hir> {
1285-
If(&'hir Expr<'hir>),
1286-
IfLet(&'hir Let<'hir>),
1287-
}
1288-
1289-
impl<'hir> Guard<'hir> {
1290-
/// Returns the body of the guard
1291-
///
1292-
/// In other words, returns the e in either of the following:
1293-
///
1294-
/// - `if e`
1295-
/// - `if let x = e`
1296-
pub fn body(&self) -> &'hir Expr<'hir> {
1297-
match self {
1298-
Guard::If(e) | Guard::IfLet(Let { init: e, .. }) => e,
1299-
}
1300-
}
1301-
}
1302-
13031283
#[derive(Debug, Clone, Copy, HashStable_Generic)]
13041284
pub struct ExprField<'hir> {
13051285
#[stable_hasher(ignore)]

compiler/rustc_hir/src/intravisit.rs

+2-7
Original file line numberDiff line numberDiff line change
@@ -619,13 +619,8 @@ pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) {
619619
pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) {
620620
visitor.visit_id(arm.hir_id);
621621
visitor.visit_pat(arm.pat);
622-
if let Some(ref g) = arm.guard {
623-
match g {
624-
Guard::If(ref e) => visitor.visit_expr(e),
625-
Guard::IfLet(ref l) => {
626-
visitor.visit_let_expr(l);
627-
}
628-
}
622+
if let Some(ref e) = arm.guard {
623+
visitor.visit_expr(e);
629624
}
630625
visitor.visit_expr(arm.body);
631626
}

compiler/rustc_hir_analysis/src/check/region.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -177,14 +177,24 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h
177177
}
178178

179179
fn resolve_arm<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, arm: &'tcx hir::Arm<'tcx>) {
180+
fn has_let_expr(expr: &Expr<'_>) -> bool {
181+
match &expr.kind {
182+
hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
183+
hir::ExprKind::Let(..) => true,
184+
_ => false,
185+
}
186+
}
187+
180188
let prev_cx = visitor.cx;
181189

182190
visitor.terminating_scopes.insert(arm.hir_id.local_id);
183191

184192
visitor.enter_node_scope_with_dtor(arm.hir_id.local_id);
185193
visitor.cx.var_parent = visitor.cx.parent;
186194

187-
if let Some(hir::Guard::If(expr)) = arm.guard {
195+
if let Some(expr) = arm.guard
196+
&& !has_let_expr(expr)
197+
{
188198
visitor.terminating_scopes.insert(expr.hir_id.local_id);
189199
}
190200

compiler/rustc_hir_pretty/src/lib.rs

+3-11
Original file line numberDiff line numberDiff line change
@@ -1874,17 +1874,9 @@ impl<'a> State<'a> {
18741874
self.print_pat(arm.pat);
18751875
self.space();
18761876
if let Some(ref g) = arm.guard {
1877-
match *g {
1878-
hir::Guard::If(e) => {
1879-
self.word_space("if");
1880-
self.print_expr(e);
1881-
self.space();
1882-
}
1883-
hir::Guard::IfLet(&hir::Let { pat, ty, init, .. }) => {
1884-
self.word_nbsp("if");
1885-
self.print_let(pat, ty, init);
1886-
}
1887-
}
1877+
self.word_space("if");
1878+
self.print_expr(g);
1879+
self.space();
18881880
}
18891881
self.word_space("=>");
18901882

compiler/rustc_hir_typeck/src/_match.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7878
let mut other_arms = vec![]; // Used only for diagnostics.
7979
let mut prior_arm = None;
8080
for arm in arms {
81-
if let Some(g) = &arm.guard {
81+
if let Some(e) = &arm.guard {
8282
self.diverges.set(Diverges::Maybe);
83-
match g {
84-
hir::Guard::If(e) => {
85-
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
86-
}
87-
hir::Guard::IfLet(l) => {
88-
self.check_expr_let(l);
89-
}
90-
};
83+
self.check_expr_has_type_or_error(e, tcx.types.bool, |_| {});
9184
}
9285

9386
self.diverges.set(Diverges::Maybe);

compiler/rustc_hir_typeck/src/expr_use_visitor.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -669,12 +669,8 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> {
669669
);
670670
self.walk_pat(discr_place, arm.pat, arm.guard.is_some());
671671

672-
match arm.guard {
673-
Some(hir::Guard::If(e)) => self.consume_expr(e),
674-
Some(hir::Guard::IfLet(l)) => {
675-
self.walk_local(l.init, l.pat, None, |t| t.borrow_expr(l.init, ty::ImmBorrow))
676-
}
677-
None => {}
672+
if let Some(ref e) = arm.guard {
673+
self.consume_expr(e)
678674
}
679675

680676
self.consume_expr(arm.body);

compiler/rustc_middle/src/thir.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -519,20 +519,13 @@ pub struct FruInfo<'tcx> {
519519
#[derive(Clone, Debug, HashStable)]
520520
pub struct Arm<'tcx> {
521521
pub pattern: Box<Pat<'tcx>>,
522-
pub guard: Option<Guard<'tcx>>,
522+
pub guard: Option<ExprId>,
523523
pub body: ExprId,
524524
pub lint_level: LintLevel,
525525
pub scope: region::Scope,
526526
pub span: Span,
527527
}
528528

529-
/// A `match` guard.
530-
#[derive(Clone, Debug, HashStable)]
531-
pub enum Guard<'tcx> {
532-
If(ExprId),
533-
IfLet(Box<Pat<'tcx>>, ExprId),
534-
}
535-
536529
#[derive(Copy, Clone, Debug, HashStable)]
537530
pub enum LogicalOp {
538531
/// The `&&` operator.

compiler/rustc_middle/src/thir/visit.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use super::{
2-
AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, Guard, InlineAsmExpr, InlineAsmOperand, Pat,
2+
AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, InlineAsmExpr, InlineAsmOperand, Pat,
33
PatKind, Stmt, StmtKind, Thir,
44
};
55

@@ -213,13 +213,8 @@ pub fn walk_arm<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
213213
visitor: &mut V,
214214
arm: &'thir Arm<'tcx>,
215215
) {
216-
match arm.guard {
217-
Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
218-
Some(Guard::IfLet(ref pat, expr)) => {
219-
visitor.visit_pat(pat);
220-
visitor.visit_expr(&visitor.thir()[expr]);
221-
}
222-
None => {}
216+
if let Some(expr) = arm.guard {
217+
visitor.visit_expr(&visitor.thir()[expr])
223218
}
224219
visitor.visit_pat(&arm.pattern);
225220
visitor.visit_expr(&visitor.thir()[arm.body]);

compiler/rustc_mir_build/src/build/expr/into.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8282
cond,
8383
Some(condition_scope),
8484
condition_scope,
85-
source_info
85+
source_info,
86+
true,
8687
));
8788

8889
this.expr_into_dest(destination, then_blk, then)
@@ -173,6 +174,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
173174
Some(condition_scope),
174175
condition_scope,
175176
source_info,
177+
true,
176178
)
177179
});
178180
let (short_circuit, continuation, constant) = match op {

0 commit comments

Comments
 (0)