Skip to content

Commit 2d61c09

Browse files
reduce false positives on some common cases from if-let-rescope
1 parent 76f3ff6 commit 2d61c09

File tree

4 files changed

+47
-40
lines changed

4 files changed

+47
-40
lines changed

compiler/rustc_lint/src/if_let_rescope.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,11 @@ fn expr_parent_is_else(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
103103
}
104104

105105
fn expr_parent_is_stmt(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool {
106-
let Some((_, hir::Node::Stmt(stmt))) = tcx.hir().parent_iter(hir_id).next() else {
107-
return false;
106+
let mut parents = tcx.hir().parent_iter(hir_id);
107+
let stmt = match parents.next() {
108+
Some((_, hir::Node::Stmt(stmt))) => stmt,
109+
Some((_, hir::Node::Block(_) | hir::Node::Arm(_))) => return true,
110+
_ => return false,
108111
};
109112
let (hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr)) = stmt.kind else { return false };
110113
expr.hir_id == hir_id

tests/ui/drop/lint-if-let-rescope.fixed

+18-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ impl Drop for Droppy {
1414
}
1515
}
1616
impl Droppy {
17-
fn get(&self) -> Option<u8> {
17+
const fn get(&self) -> Option<u8> {
1818
None
1919
}
2020
}
@@ -62,11 +62,10 @@ fn main() {
6262
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
6363
}
6464

65-
if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } {
66-
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
67-
//~| WARN: this changes meaning in Rust 2024
68-
//~| HELP: the value is now dropped here in Edition 2024
69-
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
65+
if let () = { if let Some(_value) = Droppy.get() {} } {
66+
// This should not lint.
67+
// This `if let` sits is a tail expression of a block.
68+
// In Edition 2024, the temporaries are dropped before exiting the surrounding block.
7069
}
7170

7271
#[rustfmt::skip]
@@ -94,4 +93,17 @@ fn main() {
9493
//~| HELP: the value is now dropped here in Edition 2024
9594
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
9695
}
96+
97+
// We want to keep the `if let`s below as direct descendents of match arms,
98+
// so the formatting is suppressed.
99+
#[rustfmt::skip]
100+
match droppy().get() {
101+
_ => if let Some(_value) = droppy().get() {},
102+
// Should not lint
103+
// There is implicitly a block surrounding the `if let`.
104+
// Given that it is a tail expression, the temporaries are dropped duly before
105+
// the execution is exiting the `match`.
106+
}
107+
108+
if let Some(_value) = droppy().get() {}
97109
}

tests/ui/drop/lint-if-let-rescope.rs

+17-5
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ impl Drop for Droppy {
1414
}
1515
}
1616
impl Droppy {
17-
fn get(&self) -> Option<u8> {
17+
const fn get(&self) -> Option<u8> {
1818
None
1919
}
2020
}
@@ -63,10 +63,9 @@ fn main() {
6363
}
6464

6565
if let () = { if let Some(_value) = Droppy.get() {} } {
66-
//~^ ERROR: `if let` assigns a shorter lifetime since Edition 2024
67-
//~| WARN: this changes meaning in Rust 2024
68-
//~| HELP: the value is now dropped here in Edition 2024
69-
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
66+
// This should not lint.
67+
// This `if let` sits is a tail expression of a block.
68+
// In Edition 2024, the temporaries are dropped before exiting the surrounding block.
7069
}
7170

7271
#[rustfmt::skip]
@@ -94,4 +93,17 @@ fn main() {
9493
//~| HELP: the value is now dropped here in Edition 2024
9594
//~| HELP: a `match` with a single arm can preserve the drop order up to Edition 2021
9695
}
96+
97+
// We want to keep the `if let`s below as direct descendents of match arms,
98+
// so the formatting is suppressed.
99+
#[rustfmt::skip]
100+
match droppy().get() {
101+
_ => if let Some(_value) = droppy().get() {},
102+
// Should not lint
103+
// There is implicitly a block surrounding the `if let`.
104+
// Given that it is a tail expression, the temporaries are dropped duly before
105+
// the execution is exiting the `match`.
106+
}
107+
108+
if let Some(_value) = droppy().get() {}
97109
}

tests/ui/drop/lint-if-let-rescope.stderr

+7-27
Original file line numberDiff line numberDiff line change
@@ -112,27 +112,7 @@ LL | if let Some(1) = { match Droppy.get() { Some(_value) => { Some(1) } _ =
112112
| ~~~~~ +++++++++++++++++ ~~~~ +
113113

114114
error: `if let` assigns a shorter lifetime since Edition 2024
115-
--> $DIR/lint-if-let-rescope.rs:65:22
116-
|
117-
LL | if let () = { if let Some(_value) = Droppy.get() {} } {
118-
| ^^^^^^^^^^^^^^^^^^^------^^^^^^
119-
| |
120-
| this value has a significant drop implementation which may observe a major change in drop order and requires your discretion
121-
|
122-
= warning: this changes meaning in Rust 2024
123-
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
124-
help: the value is now dropped here in Edition 2024
125-
--> $DIR/lint-if-let-rescope.rs:65:55
126-
|
127-
LL | if let () = { if let Some(_value) = Droppy.get() {} } {
128-
| ^
129-
help: a `match` with a single arm can preserve the drop order up to Edition 2021
130-
|
131-
LL | if let () = { match Droppy.get() { Some(_value) => {} _ => {}} } {
132-
| ~~~~~ +++++++++++++++++ ++++++++
133-
134-
error: `if let` assigns a shorter lifetime since Edition 2024
135-
--> $DIR/lint-if-let-rescope.rs:73:12
115+
--> $DIR/lint-if-let-rescope.rs:72:12
136116
|
137117
LL | if (if let Some(_value) = droppy().get() { true } else { false }) {
138118
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@@ -142,7 +122,7 @@ LL | if (if let Some(_value) = droppy().get() { true } else { false }) {
142122
= warning: this changes meaning in Rust 2024
143123
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
144124
help: the value is now dropped here in Edition 2024
145-
--> $DIR/lint-if-let-rescope.rs:73:53
125+
--> $DIR/lint-if-let-rescope.rs:72:53
146126
|
147127
LL | if (if let Some(_value) = droppy().get() { true } else { false }) {
148128
| ^
@@ -152,7 +132,7 @@ LL | if (match droppy().get() { Some(_value) => { true } _ => { false }}) {
152132
| ~~~~~ +++++++++++++++++ ~~~~ +
153133

154134
error: `if let` assigns a shorter lifetime since Edition 2024
155-
--> $DIR/lint-if-let-rescope.rs:79:21
135+
--> $DIR/lint-if-let-rescope.rs:78:21
156136
|
157137
LL | } else if (((if let Some(_value) = droppy().get() { true } else { false }))) {
158138
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@@ -162,7 +142,7 @@ LL | } else if (((if let Some(_value) = droppy().get() { true } else { false
162142
= warning: this changes meaning in Rust 2024
163143
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
164144
help: the value is now dropped here in Edition 2024
165-
--> $DIR/lint-if-let-rescope.rs:79:62
145+
--> $DIR/lint-if-let-rescope.rs:78:62
166146
|
167147
LL | } else if (((if let Some(_value) = droppy().get() { true } else { false }))) {
168148
| ^
@@ -172,7 +152,7 @@ LL | } else if (((match droppy().get() { Some(_value) => { true } _ => { fal
172152
| ~~~~~ +++++++++++++++++ ~~~~ +
173153

174154
error: `if let` assigns a shorter lifetime since Edition 2024
175-
--> $DIR/lint-if-let-rescope.rs:91:15
155+
--> $DIR/lint-if-let-rescope.rs:90:15
176156
|
177157
LL | while (if let Some(_value) = droppy().get() { false } else { true }) {
178158
| ^^^^^^^^^^^^^^^^^^^--------^^^^^^
@@ -182,7 +162,7 @@ LL | while (if let Some(_value) = droppy().get() { false } else { true }) {
182162
= warning: this changes meaning in Rust 2024
183163
= note: for more information, see issue #124085 <https://github.com/rust-lang/rust/issues/124085>
184164
help: the value is now dropped here in Edition 2024
185-
--> $DIR/lint-if-let-rescope.rs:91:57
165+
--> $DIR/lint-if-let-rescope.rs:90:57
186166
|
187167
LL | while (if let Some(_value) = droppy().get() { false } else { true }) {
188168
| ^
@@ -191,5 +171,5 @@ help: a `match` with a single arm can preserve the drop order up to Edition 2021
191171
LL | while (match droppy().get() { Some(_value) => { false } _ => { true }}) {
192172
| ~~~~~ +++++++++++++++++ ~~~~ +
193173

194-
error: aborting due to 8 previous errors
174+
error: aborting due to 7 previous errors
195175

0 commit comments

Comments
 (0)