Skip to content

Commit 7250a1a

Browse files
fix: assertions_on_result_states avoid changing return type in more cases (#15591)
Fixes #9916 changelog: [`assertions_on_result_states`]: avoid changing return type in more cases
2 parents 1b21661 + f4e68b2 commit 7250a1a

File tree

4 files changed

+43
-16
lines changed

4 files changed

+43
-16
lines changed

clippy_lints/src/assertions_on_result_states.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ use clippy_utils::macros::{PanicExpn, find_assert_args, root_macro_call_first_no
33
use clippy_utils::source::snippet_with_context;
44
use clippy_utils::ty::{has_debug_impl, is_copy, is_type_diagnostic_item};
55
use clippy_utils::usage::local_used_after_expr;
6-
use clippy_utils::{is_expr_final_block_expr, path_res, sym};
6+
use clippy_utils::{path_res, sym};
77
use rustc_errors::Applicability;
88
use rustc_hir::def::Res;
9-
use rustc_hir::{Expr, ExprKind};
9+
use rustc_hir::{Expr, ExprKind, Node};
1010
use rustc_lint::{LateContext, LateLintPass};
1111
use rustc_middle::ty::{self, Ty};
1212
use rustc_session::declare_lint_pass;
@@ -77,17 +77,20 @@ impl<'tcx> LateLintPass<'tcx> for AssertionsOnResultStates {
7777
_ => return,
7878
};
7979
span_lint_and_then(cx, ASSERTIONS_ON_RESULT_STATES, macro_call.span, message, |diag| {
80-
let semicolon = if is_expr_final_block_expr(cx.tcx, e) { ";" } else { "" };
8180
let mut app = Applicability::MachineApplicable;
82-
diag.span_suggestion(
83-
macro_call.span,
84-
"replace with",
85-
format!(
86-
"{}.{replacement}(){semicolon}",
87-
snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0
88-
),
89-
app,
90-
);
81+
let recv = snippet_with_context(cx, recv.span, condition.span.ctxt(), "..", &mut app).0;
82+
83+
// `assert!` doesn't return anything, but `Result::unwrap(_err)` does, so we might need to add a
84+
// semicolon to the suggestion to avoid leaking the type
85+
let sugg = match cx.tcx.parent_hir_node(e.hir_id) {
86+
// trailing expr of a block
87+
Node::Block(..) => format!("{recv}.{replacement}();"),
88+
// already has a trailing semicolon
89+
Node::Stmt(..) => format!("{recv}.{replacement}()"),
90+
// this is the last-resort option, because it's rather verbose
91+
_ => format!("{{ {recv}.{replacement}(); }}"),
92+
};
93+
diag.span_suggestion(macro_call.span, "replace with", sugg, app);
9194
});
9295
}
9396
}

tests/ui/assertions_on_result_states.fixed

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,18 @@ fn main() {
8282
assert!(r.is_err());
8383
}
8484

85-
#[allow(dead_code)]
8685
fn issue9450() {
8786
let res: Result<i32, i32> = Ok(1);
8887
res.unwrap_err();
8988
//~^ assertions_on_result_states
9089
}
90+
91+
fn issue9916(res: Result<u32, u32>) {
92+
let a = 0;
93+
match a {
94+
0 => {},
95+
1 => { res.unwrap(); },
96+
//~^ assertions_on_result_states
97+
_ => todo!(),
98+
}
99+
}

tests/ui/assertions_on_result_states.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,18 @@ fn main() {
8282
assert!(r.is_err());
8383
}
8484

85-
#[allow(dead_code)]
8685
fn issue9450() {
8786
let res: Result<i32, i32> = Ok(1);
8887
assert!(res.is_err())
8988
//~^ assertions_on_result_states
9089
}
90+
91+
fn issue9916(res: Result<u32, u32>) {
92+
let a = 0;
93+
match a {
94+
0 => {},
95+
1 => assert!(res.is_ok()),
96+
//~^ assertions_on_result_states
97+
_ => todo!(),
98+
}
99+
}

tests/ui/assertions_on_result_states.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,16 @@ LL | assert!(r.is_err());
3838
| ^^^^^^^^^^^^^^^^^^^ help: replace with: `r.unwrap_err()`
3939

4040
error: called `assert!` with `Result::is_err`
41-
--> tests/ui/assertions_on_result_states.rs:88:5
41+
--> tests/ui/assertions_on_result_states.rs:87:5
4242
|
4343
LL | assert!(res.is_err())
4444
| ^^^^^^^^^^^^^^^^^^^^^ help: replace with: `res.unwrap_err();`
4545

46-
error: aborting due to 7 previous errors
46+
error: called `assert!` with `Result::is_ok`
47+
--> tests/ui/assertions_on_result_states.rs:95:14
48+
|
49+
LL | 1 => assert!(res.is_ok()),
50+
| ^^^^^^^^^^^^^^^^^^^^ help: replace with: `{ res.unwrap(); }`
51+
52+
error: aborting due to 8 previous errors
4753

0 commit comments

Comments
 (0)