Remove thir::Guard

Use Expr instead. Use `ExprKind::Let` to represent if let guards.
This commit is contained in:
Matthew Jasper 2023-09-21 11:27:29 +00:00
parent 407cb24142
commit a549711f6e
7 changed files with 55 additions and 74 deletions

View File

@ -519,20 +519,13 @@ pub struct FruInfo<'tcx> {
#[derive(Clone, Debug, HashStable)]
pub struct Arm<'tcx> {
pub pattern: Box<Pat<'tcx>>,
pub guard: Option<Guard<'tcx>>,
pub guard: Option<ExprId>,
pub body: ExprId,
pub lint_level: LintLevel,
pub scope: region::Scope,
pub span: Span,
}
/// A `match` guard.
#[derive(Clone, Debug, HashStable)]
pub enum Guard<'tcx> {
If(ExprId),
IfLet(Box<Pat<'tcx>>, ExprId),
}
#[derive(Copy, Clone, Debug, HashStable)]
pub enum LogicalOp {
/// The `&&` operator.

View File

@ -1,5 +1,5 @@
use super::{
AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, Guard, InlineAsmExpr, InlineAsmOperand, Pat,
AdtExpr, Arm, Block, ClosureExpr, Expr, ExprKind, InlineAsmExpr, InlineAsmOperand, Pat,
PatKind, Stmt, StmtKind, Thir,
};
@ -213,13 +213,8 @@ pub fn walk_arm<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
visitor: &mut V,
arm: &'thir Arm<'tcx>,
) {
match arm.guard {
Some(Guard::If(expr)) => visitor.visit_expr(&visitor.thir()[expr]),
Some(Guard::IfLet(ref pat, expr)) => {
visitor.visit_pat(pat);
visitor.visit_expr(&visitor.thir()[expr]);
}
None => {}
if let Some(expr) = arm.guard {
visitor.visit_expr(&visitor.thir()[expr])
}
visitor.visit_pat(&arm.pattern);
visitor.visit_expr(&visitor.thir()[arm.body]);

View File

@ -425,7 +425,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
None,
arm.span,
&arm.pattern,
arm.guard.as_ref(),
arm.guard,
opt_scrutinee_place,
);
@ -717,7 +717,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
mut visibility_scope: Option<SourceScope>,
scope_span: Span,
pattern: &Pat<'tcx>,
guard: Option<&Guard<'tcx>>,
guard: Option<ExprId>,
opt_match_place: Option<(Option<&Place<'tcx>>, Span)>,
) -> Option<SourceScope> {
self.visit_primary_bindings(
@ -745,7 +745,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
);
},
);
if let Some(&Guard::If(guard_expr)) = guard {
if let Some(guard_expr) = guard {
self.declare_guard_bindings(guard_expr, scope_span, visibility_scope);
}
visibility_scope
@ -2044,7 +2044,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// * So we eagerly create the reference for the arm and then take a
// reference to that.
if let Some((arm, match_scope)) = arm_match_scope
&& let Some(guard) = &arm.guard
&& let Some(guard) = arm.guard
{
let tcx = self.tcx;
let bindings = parent_bindings
@ -2069,22 +2069,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
let mut guard_span = rustc_span::DUMMY_SP;
let (post_guard_block, otherwise_post_guard_block) =
self.in_if_then_scope(match_scope, guard_span, |this| match *guard {
Guard::If(e) => {
guard_span = this.thir[e].span;
this.then_else_break(
block,
e,
None,
match_scope,
this.source_info(arm.span),
false,
)
}
Guard::IfLet(ref pat, s) => {
guard_span = this.thir[s].span;
this.lower_let_expr(block, s, pat, match_scope, None, arm.span, false)
}
self.in_if_then_scope(match_scope, guard_span, |this| {
guard_span = this.thir[guard].span;
this.then_else_break(
block,
guard,
None,
match_scope,
this.source_info(arm.span),
false,
)
});
let source_info = self.source_info(guard_span);

View File

@ -856,7 +856,7 @@ impl<'tcx> Cx<'tcx> {
fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId {
let arm = Arm {
pattern: self.pattern_from_hir(&arm.pat),
guard: arm.guard.as_ref().map(|g| Guard::If(self.mirror_expr(g))),
guard: arm.guard.as_ref().map(|g| self.mirror_expr(g)),
body: self.mirror_expr(arm.body),
lint_level: LintLevel::Explicit(arm.hir_id),
scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },

View File

@ -100,20 +100,10 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
#[instrument(level = "trace", skip(self))]
fn visit_arm(&mut self, arm: &'p Arm<'tcx>) {
self.with_lint_level(arm.lint_level, |this| {
match arm.guard {
Some(Guard::If(expr)) => {
this.with_let_source(LetSource::IfLetGuard, |this| {
this.visit_expr(&this.thir[expr])
});
}
Some(Guard::IfLet(ref pat, expr)) => {
this.with_let_source(LetSource::IfLetGuard, |this| {
this.check_let(pat, Some(expr), pat.span);
this.visit_pat(pat);
this.visit_expr(&this.thir[expr]);
});
}
None => {}
if let Some(expr) = arm.guard {
this.with_let_source(LetSource::IfLetGuard, |this| {
this.visit_expr(&this.thir[expr])
});
}
this.visit_pat(&arm.pattern);
this.visit_expr(&self.thir[arm.body]);

View File

@ -593,9 +593,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
print_indented!(self, "pattern: ", depth_lvl + 1);
self.print_pat(pattern, depth_lvl + 2);
if let Some(guard) = guard {
if let Some(guard) = *guard {
print_indented!(self, "guard: ", depth_lvl + 1);
self.print_guard(guard, depth_lvl + 2);
self.print_expr(guard, depth_lvl + 2);
} else {
print_indented!(self, "guard: None", depth_lvl + 1);
}
@ -764,27 +764,6 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
print_indented!(self, "}", depth_lvl);
}
fn print_guard(&mut self, guard: &Guard<'tcx>, depth_lvl: usize) {
print_indented!(self, "Guard {", depth_lvl);
match guard {
Guard::If(expr_id) => {
print_indented!(self, "If (", depth_lvl + 1);
self.print_expr(*expr_id, depth_lvl + 2);
print_indented!(self, ")", depth_lvl + 1);
}
Guard::IfLet(pat, expr_id) => {
print_indented!(self, "IfLet (", depth_lvl + 1);
self.print_pat(pat, depth_lvl + 2);
print_indented!(self, ",", depth_lvl + 1);
self.print_expr(*expr_id, depth_lvl + 2);
print_indented!(self, ")", depth_lvl + 1);
}
}
print_indented!(self, "}", depth_lvl);
}
fn print_closure_expr(&mut self, expr: &ClosureExpr<'tcx>, depth_lvl: usize) {
let ClosureExpr { closure_id, args, upvars, movability, fake_reads } = expr;

View File

@ -0,0 +1,30 @@
// Tests for #88015 when using if let chains in match guards
//run-pass
#![feature(if_let_guard)]
#![feature(let_chains)]
#![allow(irrefutable_let_patterns)]
fn lhs_let(opt: Option<bool>) {
match opt {
None | Some(false) | Some(true) if let x = 42 && true => assert_eq!(x, 42),
_ => panic!()
}
}
fn rhs_let(opt: Option<bool>) {
match opt {
None | Some(false) | Some(true) if true && let x = 41 => assert_eq!(x, 41),
_ => panic!()
}
}
fn main() {
lhs_let(None);
lhs_let(Some(false));
lhs_let(Some(true));
rhs_let(None);
rhs_let(Some(false));
rhs_let(Some(true));
}