Skip to content

Commit 70610c0

Browse files
committed
lint in nested bodies if try is in outer body
1 parent 716305d commit 70610c0

File tree

4 files changed

+53
-5
lines changed

4 files changed

+53
-5
lines changed

clippy_lints/src/question_mark.rs

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub struct QuestionMark {
4949
/// very quickly, without having to walk up the parent chain, by simply checking
5050
/// if it is greater than zero.
5151
/// As for why we need this in the first place: <https://github.com/rust-lang/rust-clippy/issues/8628>
52-
try_block_depth: u32,
52+
try_block_depth_stack: Vec<u32>,
5353
}
5454
impl_lint_pass!(QuestionMark => [QUESTION_MARK]);
5555

@@ -150,7 +150,7 @@ fn expr_return_none_or_err(
150150

151151
impl QuestionMark {
152152
fn inside_try_block(&self) -> bool {
153-
self.try_block_depth > 0
153+
self.try_block_depth_stack.last() > Some(&0)
154154
}
155155

156156
/// Checks if the given expression on the given context matches the following structure:
@@ -268,13 +268,27 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMark {
268268

269269
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) {
270270
if is_try_block(cx, block) {
271-
self.try_block_depth += 1;
271+
*self
272+
.try_block_depth_stack
273+
.last_mut()
274+
.expect("blocks are always part of bodies and must have a depth") += 1;
272275
}
273276
}
274277

278+
fn check_body(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) {
279+
self.try_block_depth_stack.push(0);
280+
}
281+
282+
fn check_body_post(&mut self, _: &LateContext<'tcx>, _: &'tcx rustc_hir::Body<'tcx>) {
283+
self.try_block_depth_stack.pop();
284+
}
285+
275286
fn check_block_post(&mut self, cx: &LateContext<'tcx>, block: &'tcx rustc_hir::Block<'tcx>) {
276287
if is_try_block(cx, block) {
277-
self.try_block_depth -= 1;
288+
*self
289+
.try_block_depth_stack
290+
.last_mut()
291+
.expect("blocks are always part of bodies and must have a depth") -= 1;
278292
}
279293
}
280294
}

tests/ui/question_mark.fixed

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,16 @@ fn issue8628(a: Option<u32>) -> Option<u32> {
239239
b.or(Some(128))
240240
}
241241

242+
fn issue6828_nested_body() -> Option<u32> {
243+
try {
244+
fn f2(a: Option<i32>) -> Option<i32> {
245+
a?;
246+
Some(32)
247+
}
248+
123
249+
}
250+
}
251+
242252
// should not lint, `?` operator not available in const context
243253
const fn issue9175(option: Option<()>) -> Option<()> {
244254
if option.is_none() {

tests/ui/question_mark.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,20 @@ fn issue8628(a: Option<u32>) -> Option<u32> {
275275
b.or(Some(128))
276276
}
277277

278+
fn issue6828_nested_body() -> Option<u32> {
279+
try {
280+
fn f2(a: Option<i32>) -> Option<i32> {
281+
if a.is_none() {
282+
return None;
283+
// do lint here, the outer `try` is not relevant here
284+
// https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867
285+
}
286+
Some(32)
287+
}
288+
123
289+
}
290+
}
291+
278292
// should not lint, `?` operator not available in const context
279293
const fn issue9175(option: Option<()>) -> Option<()> {
280294
if option.is_none() {

tests/ui/question_mark.stderr

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,5 +130,15 @@ LL | | return Err(err);
130130
LL | | }
131131
| |_____^ help: replace it with: `func_returning_result()?;`
132132

133-
error: aborting due to 15 previous errors
133+
error: this block may be rewritten with the `?` operator
134+
--> $DIR/question_mark.rs:281:13
135+
|
136+
LL | / if a.is_none() {
137+
LL | | return None;
138+
LL | | // do lint here, the outer `try` is not relevant here
139+
LL | | // https://github.com/rust-lang/rust-clippy/pull/11001#issuecomment-1610636867
140+
LL | | }
141+
| |_____________^ help: replace it with: `a?;`
142+
143+
error: aborting due to 16 previous errors
134144

0 commit comments

Comments
 (0)