Skip to content

Commit 84c4b52

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 b418117 + f73e37d commit 84c4b52

11 files changed

+56
-112
lines changed

clippy_lints/src/entry.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use core::fmt::{self, Write};
88
use rustc_errors::Applicability;
99
use rustc_hir::hir_id::HirIdSet;
1010
use rustc_hir::intravisit::{walk_expr, Visitor};
11-
use rustc_hir::{Block, Expr, ExprKind, Guard, HirId, Let, Pat, Stmt, StmtKind, UnOp};
11+
use rustc_hir::{Block, Expr, ExprKind, HirId, Pat, Stmt, StmtKind, UnOp};
1212
use rustc_lint::{LateContext, LateLintPass};
1313
use rustc_session::declare_lint_pass;
1414
use rustc_span::{Span, SyntaxContext, DUMMY_SP};
@@ -465,7 +465,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> {
465465
let mut is_map_used = self.is_map_used;
466466
for arm in arms {
467467
self.visit_pat(arm.pat);
468-
if let Some(Guard::If(guard) | Guard::IfLet(&Let { init: guard, .. })) = arm.guard {
468+
if let Some(guard) = arm.guard {
469469
self.visit_non_tail_expr(guard);
470470
}
471471
is_map_used |= self.visit_cond_arm(arm.body);

clippy_lints/src/manual_clamp.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use clippy_utils::{
1111
use itertools::Itertools;
1212
use rustc_errors::{Applicability, Diagnostic};
1313
use rustc_hir::def::Res;
14-
use rustc_hir::{Arm, BinOpKind, Block, Expr, ExprKind, Guard, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind};
14+
use rustc_hir::{Arm, BinOpKind, Block, Expr, ExprKind, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind};
1515
use rustc_lint::{LateContext, LateLintPass};
1616
use rustc_middle::ty::Ty;
1717
use rustc_session::impl_lint_pass;
@@ -394,7 +394,7 @@ fn is_match_pattern<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) -> Opt
394394
// Find possible min/max branches
395395
let minmax_values = |a: &'tcx Arm<'tcx>| {
396396
if let PatKind::Binding(_, var_hir_id, _, None) = &a.pat.kind
397-
&& let Some(Guard::If(e)) = a.guard
397+
&& let Some(e) = a.guard
398398
{
399399
Some((e, var_hir_id, a.body))
400400
} else {

clippy_lints/src/matches/collapsible_match.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use clippy_utils::{
77
};
88
use rustc_errors::MultiSpan;
99
use rustc_hir::LangItem::OptionNone;
10-
use rustc_hir::{Arm, Expr, Guard, HirId, Let, Pat, PatKind};
10+
use rustc_hir::{Arm, Expr, HirId, Pat, PatKind};
1111
use rustc_lint::LateContext;
1212
use rustc_span::Span;
1313

@@ -16,7 +16,7 @@ use super::COLLAPSIBLE_MATCH;
1616
pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) {
1717
if let Some(els_arm) = arms.iter().rfind(|arm| arm_is_wild_like(cx, arm)) {
1818
for arm in arms {
19-
check_arm(cx, true, arm.pat, arm.body, arm.guard.as_ref(), Some(els_arm.body));
19+
check_arm(cx, true, arm.pat, arm.body, arm.guard, Some(els_arm.body));
2020
}
2121
}
2222
}
@@ -35,7 +35,7 @@ fn check_arm<'tcx>(
3535
outer_is_match: bool,
3636
outer_pat: &'tcx Pat<'tcx>,
3737
outer_then_body: &'tcx Expr<'tcx>,
38-
outer_guard: Option<&'tcx Guard<'tcx>>,
38+
outer_guard: Option<&'tcx Expr<'tcx>>,
3939
outer_else_body: Option<&'tcx Expr<'tcx>>,
4040
) {
4141
let inner_expr = peel_blocks_with_stmt(outer_then_body);
@@ -71,7 +71,7 @@ fn check_arm<'tcx>(
7171
// the binding must not be used in the if guard
7272
&& outer_guard.map_or(
7373
true,
74-
|(Guard::If(e) | Guard::IfLet(Let { init: e, .. }))| !is_local_used(cx, *e, binding_id)
74+
|e| !is_local_used(cx, e, binding_id)
7575
)
7676
// ...or anywhere in the inner expression
7777
&& match inner {

clippy_lints/src/matches/match_like_matches.rs

+5-18
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use clippy_utils::source::snippet_with_applicability;
44
use clippy_utils::{is_lint_allowed, is_wild, span_contains_comment};
55
use rustc_ast::{Attribute, LitKind};
66
use rustc_errors::Applicability;
7-
use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Guard, Pat, PatKind, QPath};
7+
use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, Pat, PatKind, QPath};
88
use rustc_lint::{LateContext, LintContext};
99
use rustc_middle::ty;
1010
use rustc_span::source_map::Spanned;
@@ -41,14 +41,8 @@ pub(super) fn check_match<'tcx>(
4141
find_matches_sugg(
4242
cx,
4343
scrutinee,
44-
arms.iter().map(|arm| {
45-
(
46-
cx.tcx.hir().attrs(arm.hir_id),
47-
Some(arm.pat),
48-
arm.body,
49-
arm.guard.as_ref(),
50-
)
51-
}),
44+
arms.iter()
45+
.map(|arm| (cx.tcx.hir().attrs(arm.hir_id), Some(arm.pat), arm.body, arm.guard)),
5246
e,
5347
false,
5448
)
@@ -67,14 +61,7 @@ where
6761
I: Clone
6862
+ DoubleEndedIterator
6963
+ ExactSizeIterator
70-
+ Iterator<
71-
Item = (
72-
&'a [Attribute],
73-
Option<&'a Pat<'b>>,
74-
&'a Expr<'b>,
75-
Option<&'a Guard<'b>>,
76-
),
77-
>,
64+
+ Iterator<Item = (&'a [Attribute], Option<&'a Pat<'b>>, &'a Expr<'b>, Option<&'a Expr<'b>>)>,
7865
{
7966
if !span_contains_comment(cx.sess().source_map(), expr.span)
8067
&& iter.len() >= 2
@@ -115,7 +102,7 @@ where
115102
})
116103
.join(" | ")
117104
};
118-
let pat_and_guard = if let Some(Guard::If(g)) = first_guard {
105+
let pat_and_guard = if let Some(g) = first_guard {
119106
format!(
120107
"{pat} if {}",
121108
snippet_with_applicability(cx, g.span, "..", &mut applicability)

clippy_lints/src/matches/needless_match.rs

+4-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use clippy_utils::{
88
};
99
use rustc_errors::Applicability;
1010
use rustc_hir::LangItem::OptionNone;
11-
use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, Guard, ItemKind, Node, Pat, PatKind, Path, QPath};
11+
use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatKind, Path, QPath};
1212
use rustc_lint::LateContext;
1313
use rustc_span::sym;
1414

@@ -66,18 +66,9 @@ fn check_all_arms(cx: &LateContext<'_>, match_expr: &Expr<'_>, arms: &[Arm<'_>])
6666
let arm_expr = peel_blocks_with_stmt(arm.body);
6767

6868
if let Some(guard_expr) = &arm.guard {
69-
match guard_expr {
70-
// gives up if `pat if expr` can have side effects
71-
Guard::If(if_cond) => {
72-
if if_cond.can_have_side_effects() {
73-
return false;
74-
}
75-
},
76-
// gives up `pat if let ...` arm
77-
Guard::IfLet(_) => {
78-
return false;
79-
},
80-
};
69+
if guard_expr.can_have_side_effects() {
70+
return false;
71+
}
8172
}
8273

8374
if let PatKind::Wild = arm.pat.kind {

clippy_lints/src/matches/redundant_guards.rs

+21-29
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use clippy_utils::visitors::{for_each_expr, is_local_used};
55
use rustc_ast::{BorrowKind, LitKind};
66
use rustc_errors::Applicability;
77
use rustc_hir::def::{DefKind, Res};
8-
use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, Guard, MatchSource, Node, Pat, PatKind};
8+
use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, MatchSource, Node, Pat, PatKind};
99
use rustc_lint::LateContext;
1010
use rustc_span::symbol::Ident;
1111
use rustc_span::{Span, Symbol};
@@ -21,20 +21,19 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
2121
};
2222

2323
// `Some(x) if matches!(x, y)`
24-
if let Guard::If(if_expr) = guard
25-
&& let ExprKind::Match(
26-
scrutinee,
27-
[
28-
arm,
29-
Arm {
30-
pat: Pat {
31-
kind: PatKind::Wild, ..
32-
},
33-
..
24+
if let ExprKind::Match(
25+
scrutinee,
26+
[
27+
arm,
28+
Arm {
29+
pat: Pat {
30+
kind: PatKind::Wild, ..
3431
},
35-
],
36-
MatchSource::Normal,
37-
) = if_expr.kind
32+
..
33+
},
34+
],
35+
MatchSource::Normal,
36+
) = guard.kind
3837
&& let Some(binding) = get_pat_binding(cx, scrutinee, outer_arm)
3938
{
4039
let pat_span = match (arm.pat.kind, binding.byref_ident) {
@@ -45,14 +44,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
4544
emit_redundant_guards(
4645
cx,
4746
outer_arm,
48-
if_expr.span,
47+
guard.span,
4948
snippet(cx, pat_span, "<binding>"),
5049
&binding,
5150
arm.guard,
5251
);
5352
}
5453
// `Some(x) if let Some(2) = x`
55-
else if let Guard::IfLet(let_expr) = guard
54+
else if let ExprKind::Let(let_expr) = guard.kind
5655
&& let Some(binding) = get_pat_binding(cx, let_expr.init, outer_arm)
5756
{
5857
let pat_span = match (let_expr.pat.kind, binding.byref_ident) {
@@ -71,8 +70,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
7170
}
7271
// `Some(x) if x == Some(2)`
7372
// `Some(x) if Some(2) == x`
74-
else if let Guard::If(if_expr) = guard
75-
&& let ExprKind::Binary(bin_op, local, pat) = if_expr.kind
73+
else if let ExprKind::Binary(bin_op, local, pat) = guard.kind
7674
&& matches!(bin_op.node, BinOpKind::Eq)
7775
// Ensure they have the same type. If they don't, we'd need deref coercion which isn't
7876
// possible (currently) in a pattern. In some cases, you can use something like
@@ -96,16 +94,15 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'tcx>]) {
9694
emit_redundant_guards(
9795
cx,
9896
outer_arm,
99-
if_expr.span,
97+
guard.span,
10098
snippet(cx, pat_span, "<binding>"),
10199
&binding,
102100
None,
103101
);
104-
} else if let Guard::If(if_expr) = guard
105-
&& let ExprKind::MethodCall(path, recv, args, ..) = if_expr.kind
102+
} else if let ExprKind::MethodCall(path, recv, args, ..) = guard.kind
106103
&& let Some(binding) = get_pat_binding(cx, recv, outer_arm)
107104
{
108-
check_method_calls(cx, outer_arm, path.ident.name, recv, args, if_expr, &binding);
105+
check_method_calls(cx, outer_arm, path.ident.name, recv, args, guard, &binding);
109106
}
110107
}
111108
}
@@ -216,7 +213,7 @@ fn emit_redundant_guards<'tcx>(
216213
guard_span: Span,
217214
binding_replacement: Cow<'static, str>,
218215
pat_binding: &PatBindingInfo,
219-
inner_guard: Option<Guard<'_>>,
216+
inner_guard: Option<&Expr<'_>>,
220217
) {
221218
span_lint_and_then(
222219
cx,
@@ -242,12 +239,7 @@ fn emit_redundant_guards<'tcx>(
242239
(
243240
guard_span.source_callsite().with_lo(outer_arm.pat.span.hi()),
244241
inner_guard.map_or_else(String::new, |guard| {
245-
let (prefix, span) = match guard {
246-
Guard::If(e) => ("if", e.span),
247-
Guard::IfLet(l) => ("if let", l.span),
248-
};
249-
250-
format!(" {prefix} {}", snippet(cx, span, "<guard>"))
242+
format!(" if {}", snippet(cx, guard.span, "<guard>"))
251243
}),
252244
),
253245
],

clippy_lints/src/matches/redundant_pattern_match.rs

+9-11
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use rustc_ast::ast::LitKind;
99
use rustc_errors::Applicability;
1010
use rustc_hir::def::{DefKind, Res};
1111
use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
12-
use rustc_hir::{Arm, Expr, ExprKind, Guard, Node, Pat, PatKind, QPath, UnOp};
12+
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
1313
use rustc_lint::LateContext;
1414
use rustc_middle::ty::{self, GenericArgKind, Ty};
1515
use rustc_span::{sym, Span, Symbol};
@@ -277,8 +277,6 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op
277277
let mut sugg = format!("{}.{good_method}", snippet(cx, result_expr.span, "_"));
278278

279279
if let Some(guard) = maybe_guard {
280-
let Guard::If(guard) = *guard else { return }; // `...is_none() && let ...` is a syntax error
281-
282280
// wow, the HIR for match guards in `PAT if let PAT = expr && expr => ...` is annoying!
283281
// `guard` here is `Guard::If` with the let expression somewhere deep in the tree of exprs,
284282
// counter to the intuition that it should be `Guard::IfLet`, so we need another check
@@ -319,7 +317,7 @@ fn found_good_method<'tcx>(
319317
cx: &LateContext<'_>,
320318
arms: &'tcx [Arm<'tcx>],
321319
node: (&PatKind<'_>, &PatKind<'_>),
322-
) -> Option<(&'static str, Option<&'tcx Guard<'tcx>>)> {
320+
) -> Option<(&'static str, Option<&'tcx Expr<'tcx>>)> {
323321
match node {
324322
(
325323
PatKind::TupleStruct(ref path_left, patterns_left, _),
@@ -409,7 +407,7 @@ fn get_good_method<'tcx>(
409407
cx: &LateContext<'_>,
410408
arms: &'tcx [Arm<'tcx>],
411409
path_left: &QPath<'_>,
412-
) -> Option<(&'static str, Option<&'tcx Guard<'tcx>>)> {
410+
) -> Option<(&'static str, Option<&'tcx Expr<'tcx>>)> {
413411
if let Some(name) = get_ident(path_left) {
414412
let (expected_item_left, should_be_left, should_be_right) = match name.as_str() {
415413
"Ok" => (Item::Lang(ResultOk), "is_ok()", "is_err()"),
@@ -478,7 +476,7 @@ fn find_good_method_for_match<'a, 'tcx>(
478476
expected_item_right: Item,
479477
should_be_left: &'a str,
480478
should_be_right: &'a str,
481-
) -> Option<(&'a str, Option<&'tcx Guard<'tcx>>)> {
479+
) -> Option<(&'a str, Option<&'tcx Expr<'tcx>>)> {
482480
let first_pat = arms[0].pat;
483481
let second_pat = arms[1].pat;
484482

@@ -496,8 +494,8 @@ fn find_good_method_for_match<'a, 'tcx>(
496494

497495
match body_node_pair {
498496
(ExprKind::Lit(lit_left), ExprKind::Lit(lit_right)) => match (&lit_left.node, &lit_right.node) {
499-
(LitKind::Bool(true), LitKind::Bool(false)) => Some((should_be_left, arms[0].guard.as_ref())),
500-
(LitKind::Bool(false), LitKind::Bool(true)) => Some((should_be_right, arms[1].guard.as_ref())),
497+
(LitKind::Bool(true), LitKind::Bool(false)) => Some((should_be_left, arms[0].guard)),
498+
(LitKind::Bool(false), LitKind::Bool(true)) => Some((should_be_right, arms[1].guard)),
501499
_ => None,
502500
},
503501
_ => None,
@@ -511,7 +509,7 @@ fn find_good_method_for_matches_macro<'a, 'tcx>(
511509
expected_item_left: Item,
512510
should_be_left: &'a str,
513511
should_be_right: &'a str,
514-
) -> Option<(&'a str, Option<&'tcx Guard<'tcx>>)> {
512+
) -> Option<(&'a str, Option<&'tcx Expr<'tcx>>)> {
515513
let first_pat = arms[0].pat;
516514

517515
let body_node_pair = if is_pat_variant(cx, first_pat, path_left, expected_item_left) {
@@ -522,8 +520,8 @@ fn find_good_method_for_matches_macro<'a, 'tcx>(
522520

523521
match body_node_pair {
524522
(ExprKind::Lit(lit_left), ExprKind::Lit(lit_right)) => match (&lit_left.node, &lit_right.node) {
525-
(LitKind::Bool(true), LitKind::Bool(false)) => Some((should_be_left, arms[0].guard.as_ref())),
526-
(LitKind::Bool(false), LitKind::Bool(true)) => Some((should_be_right, arms[1].guard.as_ref())),
523+
(LitKind::Bool(true), LitKind::Bool(false)) => Some((should_be_left, arms[0].guard)),
524+
(LitKind::Bool(false), LitKind::Bool(true)) => Some((should_be_right, arms[1].guard)),
527525
_ => None,
528526
},
529527
_ => None,

clippy_lints/src/mixed_read_write_in_expression.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::{span_lint, span_lint_and_note};
22
use clippy_utils::{get_parent_expr, path_to_local, path_to_local_id};
33
use rustc_hir::intravisit::{walk_expr, Visitor};
4-
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, Stmt, StmtKind};
4+
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Local, Node, Stmt, StmtKind};
55
use rustc_lint::{LateContext, LateLintPass};
66
use rustc_middle::ty;
77
use rustc_session::declare_lint_pass;
@@ -119,7 +119,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
119119
ExprKind::Match(e, arms, _) => {
120120
self.visit_expr(e);
121121
for arm in arms {
122-
if let Some(Guard::If(if_expr)) = arm.guard {
122+
if let Some(if_expr) = arm.guard {
123123
self.visit_expr(if_expr);
124124
}
125125
// make sure top level arm expressions aren't linted

clippy_lints/src/utils/author.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -318,17 +318,11 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
318318
self.pat(field!(arm.pat));
319319
match arm.value.guard {
320320
None => chain!(self, "{arm}.guard.is_none()"),
321-
Some(hir::Guard::If(expr)) => {
321+
Some(expr) => {
322322
bind!(self, expr);
323-
chain!(self, "let Some(Guard::If({expr})) = {arm}.guard");
323+
chain!(self, "let Some({expr}) = {arm}.guard");
324324
self.expr(expr);
325325
},
326-
Some(hir::Guard::IfLet(let_expr)) => {
327-
bind!(self, let_expr);
328-
chain!(self, "let Some(Guard::IfLet({let_expr}) = {arm}.guard");
329-
self.pat(field!(let_expr.pat));
330-
self.expr(field!(let_expr.init));
331-
},
332326
}
333327
self.expr(field!(arm.body));
334328
}

0 commit comments

Comments
 (0)