Skip to content

Commit 075e491

Browse files
Not linting irrefutable_let_patterns on let chains
1 parent 9f2ef0f commit 075e491

File tree

7 files changed

+144
-234
lines changed

7 files changed

+144
-234
lines changed

compiler/rustc_mir_build/src/errors.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -765,22 +765,6 @@ pub(crate) struct LowerRangeBoundMustBeLessThanUpper {
765765
pub(crate) span: Span,
766766
}
767767

768-
#[derive(LintDiagnostic)]
769-
#[diag(mir_build_leading_irrefutable_let_patterns)]
770-
#[note]
771-
#[help]
772-
pub(crate) struct LeadingIrrefutableLetPatterns {
773-
pub(crate) count: usize,
774-
}
775-
776-
#[derive(LintDiagnostic)]
777-
#[diag(mir_build_trailing_irrefutable_let_patterns)]
778-
#[note]
779-
#[help]
780-
pub(crate) struct TrailingIrrefutableLetPatterns {
781-
pub(crate) count: usize,
782-
}
783-
784768
#[derive(LintDiagnostic)]
785769
#[diag(mir_build_bindings_with_variant_name, code = E0170)]
786770
pub(crate) struct BindingsWithVariantName {

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 6 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ impl<'p, 'tcx> Visitor<'p, 'tcx> for MatchVisitor<'p, 'tcx> {
168168
{
169169
let mut chain_refutabilities = Vec::new();
170170
let Ok(()) = self.visit_land(ex, &mut chain_refutabilities) else { return };
171-
// If at least one of the operands is a `let ... = ...`.
172-
if chain_refutabilities.iter().any(|x| x.is_some()) {
173-
self.check_let_chain(chain_refutabilities, ex.span);
171+
// For let chains, don't lint.
172+
if let [Some((_, refutability))] = chain_refutabilities[..] {
173+
self.check_single_let(refutability, ex.span);
174174
}
175175
return;
176176
}
@@ -562,73 +562,16 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
562562
}
563563

564564
#[instrument(level = "trace", skip(self))]
565-
fn check_let_chain(
566-
&mut self,
567-
chain_refutabilities: Vec<Option<(Span, RefutableFlag)>>,
568-
whole_chain_span: Span,
569-
) {
565+
fn check_single_let(&mut self, refutability: RefutableFlag, whole_chain_span: Span) {
570566
assert!(self.let_source != LetSource::None);
571-
572-
if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, Irrefutable)))) {
573-
// The entire chain is made up of irrefutable `let` statements
567+
if matches!(refutability, Irrefutable) {
574568
report_irrefutable_let_patterns(
575569
self.tcx,
576570
self.lint_level,
577571
self.let_source,
578-
chain_refutabilities.len(),
572+
1,
579573
whole_chain_span,
580574
);
581-
return;
582-
}
583-
584-
if let Some(until) =
585-
chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, Irrefutable))))
586-
&& until > 0
587-
{
588-
// The chain has a non-zero prefix of irrefutable `let` statements.
589-
590-
// Check if the let source is while, for there is no alternative place to put a prefix,
591-
// and we shouldn't lint.
592-
// For let guards inside a match, prefixes might use bindings of the match pattern,
593-
// so can't always be moved out.
594-
// For `else if let`, an extra indentation level would be required to move the bindings.
595-
// FIXME: Add checking whether the bindings are actually used in the prefix,
596-
// and lint if they are not.
597-
if !matches!(
598-
self.let_source,
599-
LetSource::WhileLet | LetSource::IfLetGuard | LetSource::ElseIfLet
600-
) {
601-
// Emit the lint
602-
let prefix = &chain_refutabilities[..until];
603-
let span_start = prefix[0].unwrap().0;
604-
let span_end = prefix.last().unwrap().unwrap().0;
605-
let span = span_start.to(span_end);
606-
let count = prefix.len();
607-
self.tcx.emit_node_span_lint(
608-
IRREFUTABLE_LET_PATTERNS,
609-
self.lint_level,
610-
span,
611-
LeadingIrrefutableLetPatterns { count },
612-
);
613-
}
614-
}
615-
616-
if let Some(from) =
617-
chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, Irrefutable))))
618-
&& from != (chain_refutabilities.len() - 1)
619-
{
620-
// The chain has a non-empty suffix of irrefutable `let` statements
621-
let suffix = &chain_refutabilities[from + 1..];
622-
let span_start = suffix[0].unwrap().0;
623-
let span_end = suffix.last().unwrap().unwrap().0;
624-
let span = span_start.to(span_end);
625-
let count = suffix.len();
626-
self.tcx.emit_node_span_lint(
627-
IRREFUTABLE_LET_PATTERNS,
628-
self.lint_level,
629-
span,
630-
TrailingIrrefutableLetPatterns { count },
631-
);
632575
}
633576
}
634577

compiler/rustc_mir_transform/src/check_alignment.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ fn insert_alignment_check<'tcx>(
8282

8383
// If this target does not have reliable alignment, further limit the mask by anding it with
8484
// the mask for the highest reliable alignment.
85-
#[allow(irrefutable_let_patterns)]
85+
#[cfg_attr(bootstrap, expect(irrefutable_let_patterns))]
8686
if let max_align = tcx.sess.target.max_reliable_alignment()
8787
&& max_align < Align::MAX
8888
{

src/tools/miri/src/shims/foreign_items.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
900900
// Fallback to shims in submodules.
901901
_ => {
902902
// Math shims
903-
#[expect(irrefutable_let_patterns)]
903+
#[cfg_attr(bootstrap, expect(irrefutable_let_patterns))]
904904
if let res = shims::math::EvalContextExt::emulate_foreign_item_inner(
905905
this, link_name, abi, args, dest,
906906
)? && !matches!(res, EmulateItemResult::NotSupported)
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//@ edition: 2024
2+
3+
#![feature(if_let_guard)]
4+
5+
use std::ops::Range;
6+
7+
fn main() {
8+
let opt = Some(None..Some(1));
9+
10+
if let first = &opt {}
11+
//~^ WARN irrefutable `if let` pattern
12+
13+
if let first = &opt
14+
&& let Some(second) = first
15+
{}
16+
17+
if let first = &opt
18+
&& let (a, b) = (1, 2)
19+
{}
20+
21+
if let first = &opt
22+
&& let None = Some(1)
23+
{}
24+
25+
if 4 * 2 == 0
26+
&& let first = &opt
27+
{}
28+
29+
if let first = &opt
30+
&& let Some(second) = first
31+
&& let None = second.start
32+
&& let v = 0
33+
{}
34+
35+
if let Some(ref first) = opt
36+
&& let second = first
37+
&& let _third = second
38+
{}
39+
40+
if let Range { start: local_start, end: _ } = (None..Some(1))
41+
&& let None = local_start
42+
{}
43+
44+
if let Range { start: local_start, end: _ } = (None..Some(1)) {}
45+
//~^ WARN irrefutable `if let` pattern
46+
47+
if let (a, b, c) = (Some(1), Some(1), Some(1)) {}
48+
//~^ WARN irrefutable `if let` pattern
49+
50+
if let (a, b, c) = (Some(1), Some(1), Some(1))
51+
&& let None = Some(1)
52+
{}
53+
54+
if let Some(ref first) = opt
55+
&& let Range { start: local_start, end: _ } = first
56+
&& let None = local_start
57+
{}
58+
59+
match opt {
60+
Some(ref first) if let second = first => {}
61+
//~^ WARN irrefutable `if let` guard pattern
62+
_ => {}
63+
}
64+
65+
match opt {
66+
Some(ref first)
67+
if let second = first
68+
&& let _third = second
69+
&& let v = 4 + 4 => {}
70+
_ => {}
71+
}
72+
73+
match opt {
74+
Some(ref first)
75+
if let Range { start: local_start, end: _ } = first
76+
&& let None = local_start => {}
77+
_ => {}
78+
}
79+
80+
match opt {
81+
Some(ref first)
82+
if let Range { start: Some(_), end: local_end } = first
83+
&& let v = local_end
84+
&& let w = v => {}
85+
_ => {}
86+
}
87+
88+
while let first = &opt {}
89+
//~^ WARN irrefutable `while let` pattern
90+
91+
while let first = &opt
92+
&& let (a, b) = (1, 2)
93+
{}
94+
95+
while let first = &opt
96+
&& let Some(second) = first
97+
&& let None = second.start
98+
{}
99+
100+
while let Some(ref first) = opt
101+
&& let second = first
102+
&& let _third = second
103+
{}
104+
105+
while let Some(ref first) = opt
106+
&& let Range { start: local_start, end: _ } = first
107+
&& let None = local_start
108+
{}
109+
110+
if opt == Some(None..None) {
111+
} else if let x = opt.clone().map(|_| 1) {
112+
//~^ WARN irrefutable `if let` pattern
113+
}
114+
115+
if opt == Some(None..None) {
116+
} else if let x = opt.clone().map(|_| 1)
117+
&& x == Some(1)
118+
{
119+
}
120+
121+
if opt == Some(None..None) {
122+
} else if opt.is_some()
123+
&& let x = &opt
124+
{
125+
}
126+
127+
if opt == Some(None..None) {
128+
} else {
129+
if let x = opt.clone().map(|_| 1)
130+
&& x == Some(1)
131+
{}
132+
}
133+
}

tests/ui/rfcs/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr

Lines changed: 0 additions & 133 deletions
This file was deleted.

0 commit comments

Comments
 (0)