Skip to content

Commit f962f2f

Browse files
committed
fix: if_then_some_else_none FP when require type coercion
1 parent 7e2d26f commit f962f2f

6 files changed

+89
-1
lines changed

clippy_lints/src/if_then_some_else_none.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use rustc_errors::Applicability;
1111
use rustc_hir::LangItem::{OptionNone, OptionSome};
1212
use rustc_hir::{Expr, ExprKind};
1313
use rustc_lint::{LateContext, LateLintPass, LintContext};
14+
use rustc_middle::ty::adjustment::{Adjust, AutoBorrow};
1415
use rustc_session::impl_lint_pass;
1516

1617
declare_clippy_lint! {
@@ -92,6 +93,10 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
9293
expr.span,
9394
format!("this could be simplified with `bool::{method_name}`"),
9495
|diag| {
96+
if !expr_requires_manual_adjustment(cx, then_arg) {
97+
return;
98+
}
99+
95100
let mut app = Applicability::MachineApplicable;
96101
let cond_snip = Sugg::hir_with_context(cx, cond, expr.span.ctxt(), "[condition]", &mut app)
97102
.maybe_paren()
@@ -119,3 +124,12 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
119124
}
120125
}
121126
}
127+
128+
fn expr_requires_manual_adjustment(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
129+
cx.typeck_results().expr_adjustments(expr).iter().all(|adj| {
130+
matches!(
131+
adj.kind,
132+
Adjust::Deref(None) | Adjust::Borrow(AutoBorrow::Ref(..)) | Adjust::ReborrowPin(_)
133+
)
134+
})
135+
}

tests/ui/if_then_some_else_none.fixed

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,14 @@ const fn issue12103(x: u32) -> Option<u32> {
122122
// Should not issue an error in `const` context
123123
if x > 42 { Some(150) } else { None }
124124
}
125+
126+
mod issue15257 {
127+
struct Range {
128+
start: u8,
129+
end: u8,
130+
}
131+
132+
fn can_be_safely_rewrite(rs: &[&Range]) -> Option<Vec<u8>> {
133+
(rs.len() == 1 && rs[0].start == rs[0].end).then(|| vec![rs[0].start])
134+
}
135+
}

tests/ui/if_then_some_else_none.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,19 @@ const fn issue12103(x: u32) -> Option<u32> {
143143
// Should not issue an error in `const` context
144144
if x > 42 { Some(150) } else { None }
145145
}
146+
147+
mod issue15257 {
148+
struct Range {
149+
start: u8,
150+
end: u8,
151+
}
152+
153+
fn can_be_safely_rewrite(rs: &[&Range]) -> Option<Vec<u8>> {
154+
if rs.len() == 1 && rs[0].start == rs[0].end {
155+
//~^ if_then_some_else_none
156+
Some(vec![rs[0].start])
157+
} else {
158+
None
159+
}
160+
}
161+
}

tests/ui/if_then_some_else_none.stderr

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,16 @@ error: this could be simplified with `bool::then`
5858
LL | if s == "1" { Some(true) } else { None }
5959
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(s == "1").then(|| true)`
6060

61-
error: aborting due to 6 previous errors
61+
error: this could be simplified with `bool::then`
62+
--> tests/ui/if_then_some_else_none.rs:154:9
63+
|
64+
LL | / if rs.len() == 1 && rs[0].start == rs[0].end {
65+
LL | |
66+
LL | | Some(vec![rs[0].start])
67+
LL | | } else {
68+
LL | | None
69+
LL | | }
70+
| |_________^ help: try: `(rs.len() == 1 && rs[0].start == rs[0].end).then(|| vec![rs[0].start])`
71+
72+
error: aborting due to 7 previous errors
6273

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//@no-rustfix
2+
3+
#![warn(clippy::if_then_some_else_none)]
4+
#![allow(clippy::manual_is_multiple_of)]
5+
6+
mod issue15257 {
7+
#[derive(Default)]
8+
pub struct Foo {}
9+
pub trait Bar {}
10+
impl Bar for Foo {}
11+
12+
fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> {
13+
if i % 2 == 0 {
14+
//~^ if_then_some_else_none
15+
Some(Box::new(Foo::default()))
16+
} else {
17+
None
18+
}
19+
}
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: this could be simplified with `bool::then`
2+
--> tests/ui/if_then_some_else_none_unfixable.rs:13:9
3+
|
4+
LL | / if i % 2 == 0 {
5+
LL | |
6+
LL | | Some(Box::new(Foo::default()))
7+
LL | | } else {
8+
LL | | None
9+
LL | | }
10+
| |_________^
11+
|
12+
= note: `-D clippy::if-then-some-else-none` implied by `-D warnings`
13+
= help: to override `-D warnings` add `#[allow(clippy::if_then_some_else_none)]`
14+
15+
error: aborting due to 1 previous error
16+

0 commit comments

Comments
 (0)