diff options
| author | dswij <dharmasw@outlook.com> | 2025-03-26 05:08:33 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-26 05:08:33 +0000 |
| commit | 939d5f93eb62f3237f4b35fbaba1226b3340b3e6 (patch) | |
| tree | 1ec4b9363fc6fb13392f6fe868e03b82a208babb | |
| parent | 4517b4260f0add8ecb4761ed7ca537a6d22f7ec3 (diff) | |
| parent | 8bc164b81824a1d13a6cb10ebe6d169cea82916e (diff) | |
| download | rust-939d5f93eb62f3237f4b35fbaba1226b3340b3e6.tar.gz rust-939d5f93eb62f3237f4b35fbaba1226b3340b3e6.zip | |
fix: `option_if_let_else` suggests wrongly when coercion requires explicit cast (#14389)
Closes #11059 changelog: `option_if_let_else`: fix wrong suggestion when coersion requires explicit cast
| -rw-r--r-- | clippy_lints/src/option_if_let_else.rs | 13 | ||||
| -rw-r--r-- | tests/ui/option_if_let_else.fixed | 14 | ||||
| -rw-r--r-- | tests/ui/option_if_let_else.rs | 14 |
3 files changed, 39 insertions, 2 deletions
diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index f37f3a12d4e..9487cec87ef 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -4,8 +4,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; use clippy_utils::ty::is_copy; use clippy_utils::{ - CaptureKind, can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context, - is_res_lang_ctor, peel_blocks, peel_hir_expr_while, + CaptureKind, can_move_expr_to_closure, eager_or_lazy, expr_requires_coercion, higher, is_else_clause, + is_in_const_context, is_res_lang_ctor, peel_blocks, peel_hir_expr_while, }; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -212,6 +212,15 @@ fn try_get_option_occurrence<'tcx>( } } + let some_body_ty = cx.typeck_results().expr_ty(some_body); + let none_body_ty = cx.typeck_results().expr_ty(none_body); + // Check if coercion is needed for the `None` arm. If so, we cannot suggest because it will + // introduce a type mismatch. A special case is when both arms have the same type, then + // coercion is fine. + if some_body_ty != none_body_ty && expr_requires_coercion(cx, none_body) { + return None; + } + let mut app = Applicability::Unspecified; let (none_body, is_argless_call) = match none_body.kind { diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index ee309889601..fe3ac9e8f92 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -288,3 +288,17 @@ mod issue13964 { }; } } + +mod issue11059 { + use std::fmt::Debug; + + fn box_coercion_unsize(o: Option<i32>) -> Box<dyn Debug> { + if let Some(o) = o { Box::new(o) } else { Box::new("foo") } + } + + static S: String = String::new(); + + fn deref_with_overload(o: Option<&str>) -> &str { + if let Some(o) = o { o } else { &S } + } +} diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 525a5df4371..5b7498bc8e2 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -351,3 +351,17 @@ mod issue13964 { }; } } + +mod issue11059 { + use std::fmt::Debug; + + fn box_coercion_unsize(o: Option<i32>) -> Box<dyn Debug> { + if let Some(o) = o { Box::new(o) } else { Box::new("foo") } + } + + static S: String = String::new(); + + fn deref_with_overload(o: Option<&str>) -> &str { + if let Some(o) = o { o } else { &S } + } +} |
