Skip to content

Commit 939d5f9

Browse files
authored
fix: option_if_let_else suggests wrongly when coercion requires explicit cast (rust-lang#14389)
Closes rust-lang#11059 changelog: `option_if_let_else`: fix wrong suggestion when coersion requires explicit cast
2 parents 4517b42 + 8bc164b commit 939d5f9

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

clippy_lints/src/option_if_let_else.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
44
use clippy_utils::sugg::Sugg;
55
use clippy_utils::ty::is_copy;
66
use clippy_utils::{
7-
CaptureKind, can_move_expr_to_closure, eager_or_lazy, higher, is_else_clause, is_in_const_context,
8-
is_res_lang_ctor, peel_blocks, peel_hir_expr_while,
7+
CaptureKind, can_move_expr_to_closure, eager_or_lazy, expr_requires_coercion, higher, is_else_clause,
8+
is_in_const_context, is_res_lang_ctor, peel_blocks, peel_hir_expr_while,
99
};
1010
use rustc_data_structures::fx::FxHashSet;
1111
use rustc_errors::Applicability;
@@ -212,6 +212,15 @@ fn try_get_option_occurrence<'tcx>(
212212
}
213213
}
214214

215+
let some_body_ty = cx.typeck_results().expr_ty(some_body);
216+
let none_body_ty = cx.typeck_results().expr_ty(none_body);
217+
// Check if coercion is needed for the `None` arm. If so, we cannot suggest because it will
218+
// introduce a type mismatch. A special case is when both arms have the same type, then
219+
// coercion is fine.
220+
if some_body_ty != none_body_ty && expr_requires_coercion(cx, none_body) {
221+
return None;
222+
}
223+
215224
let mut app = Applicability::Unspecified;
216225

217226
let (none_body, is_argless_call) = match none_body.kind {

tests/ui/option_if_let_else.fixed

+14
Original file line numberDiff line numberDiff line change
@@ -288,3 +288,17 @@ mod issue13964 {
288288
};
289289
}
290290
}
291+
292+
mod issue11059 {
293+
use std::fmt::Debug;
294+
295+
fn box_coercion_unsize(o: Option<i32>) -> Box<dyn Debug> {
296+
if let Some(o) = o { Box::new(o) } else { Box::new("foo") }
297+
}
298+
299+
static S: String = String::new();
300+
301+
fn deref_with_overload(o: Option<&str>) -> &str {
302+
if let Some(o) = o { o } else { &S }
303+
}
304+
}

tests/ui/option_if_let_else.rs

+14
Original file line numberDiff line numberDiff line change
@@ -351,3 +351,17 @@ mod issue13964 {
351351
};
352352
}
353353
}
354+
355+
mod issue11059 {
356+
use std::fmt::Debug;
357+
358+
fn box_coercion_unsize(o: Option<i32>) -> Box<dyn Debug> {
359+
if let Some(o) = o { Box::new(o) } else { Box::new("foo") }
360+
}
361+
362+
static S: String = String::new();
363+
364+
fn deref_with_overload(o: Option<&str>) -> &str {
365+
if let Some(o) = o { o } else { &S }
366+
}
367+
}

0 commit comments

Comments
 (0)