Skip to content

Commit b6b3b68

Browse files
committed
Fixes #14876
The `manual_unwrap_or` lint was incorrectly suggesting `unwrap_or_default()` when the MSRV was set to 1.15 or lower, even though `unwrap_or_default()` was only stabilized in Rust 1.16. Changes made: 1. Fixed the MSRV check in `manual_unwrap_or.rs` to use the correct constant `msrvs::UNWRAP_OR_DEFAULT` instead of `msrvs::STR_REPEAT` 2. Added the `UNWRAP_OR_DEFAULT` constant to the MSRV aliases in `msrvs.rs`, marking it as stabilized in Rust 1.16 This ensures that the lint will only suggest using `unwrap_or_default()` when the MSRV is at least 1.16. changelog: Fix [`manual_unwrap_or`] false positive when MSRV is below 1.16 On branch Fix-`manual_unwrap_or`-lint-to-respect-MSRV-for-`unwrap_or_default()` Changes to be committed: modified: clippy_lints/src/matches/manual_unwrap_or.rs modified: clippy_lints/src/matches/mod.rs modified: clippy_utils/src/msrvs.rs
1 parent 5dccb10 commit b6b3b68

File tree

3 files changed

+32
-24
lines changed

3 files changed

+32
-24
lines changed

clippy_lints/src/matches/manual_unwrap_or.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use clippy_utils::consts::ConstEvalCtxt;
2+
use clippy_utils::msrvs::{self, Msrv};
23
use clippy_utils::source::{SpanRangeExt as _, indent_of, reindent_multiline};
34
use rustc_ast::{BindingMode, ByRef};
45
use rustc_errors::Applicability;
@@ -82,6 +83,7 @@ fn handle(
8283
body_some: &Expr<'_>,
8384
body_none: &Expr<'_>,
8485
binding_id: HirId,
86+
msrv: Msrv,
8587
) {
8688
// Only deal with situations where both alternatives return the same non-adjusted type.
8789
if cx.typeck_results().expr_ty(body_some) != cx.typeck_results().expr_ty(body_none) {
@@ -112,6 +114,8 @@ fn handle(
112114
&& let GenericArgKind::Type(condition_ty) = condition_ty.unpack()
113115
&& implements_trait(cx, condition_ty, default_trait_id, &[])
114116
&& is_default_equivalent(cx, peel_blocks(body_none))
117+
// Check if MSRV meets the requirement for unwrap_or_default (stabilized in 1.16)
118+
&& msrv.meets(cx, msrvs::UNWRAP_OR_DEFAULT)
115119
{
116120
// We now check if the condition is a None variant, in which case we need to specify the type
117121
if path_res(cx, condition)
@@ -186,6 +190,7 @@ pub fn check_match<'tcx>(
186190
expr: &'tcx Expr<'tcx>,
187191
scrutinee: &'tcx Expr<'tcx>,
188192
arms: &'tcx [Arm<'tcx>],
193+
msrv: Msrv,
189194
) {
190195
if let [arm1, arm2] = arms
191196
// Make sure there are no guards to keep things simple
@@ -194,7 +199,7 @@ pub fn check_match<'tcx>(
194199
// Get the some and none bodies and the binding id of the some arm
195200
&& let Some(((body_some, binding_id), body_none)) = get_some_and_none_bodies(cx, arm1, arm2)
196201
{
197-
handle(cx, expr, "match", scrutinee, body_some, body_none, binding_id);
202+
handle(cx, expr, "match", scrutinee, body_some, body_none, binding_id, msrv);
198203
}
199204
}
200205

@@ -205,6 +210,7 @@ pub fn check_if_let<'tcx>(
205210
scrutinee: &'tcx Expr<'tcx>,
206211
then_expr: &'tcx Expr<'tcx>,
207212
else_expr: &'tcx Expr<'tcx>,
213+
msrv: Msrv,
208214
) {
209215
if let Some(binding_id) = get_some(cx, pat) {
210216
handle(
@@ -215,6 +221,7 @@ pub fn check_if_let<'tcx>(
215221
peel_blocks(then_expr),
216222
peel_blocks(else_expr),
217223
binding_id,
224+
msrv,
218225
);
219226
}
220227
}

clippy_lints/src/matches/mod.rs

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,37 +1062,37 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
10621062
if is_direct_expn_of(expr.span, sym::matches).is_some()
10631063
&& let [arm, _] = arms
10641064
{
1065-
redundant_pattern_match::check_match(cx, expr, ex, arms);
1065+
redundant_pattern_match::check_match(cx, expr, ex, &arms);
10661066
redundant_pattern_match::check_matches_true(cx, expr, arm, ex);
10671067
}
10681068

10691069
if source == MatchSource::Normal && !is_span_match(cx, expr.span) {
10701070
return;
10711071
}
10721072
if matches!(source, MatchSource::Normal | MatchSource::ForLoopDesugar) {
1073-
significant_drop_in_scrutinee::check_match(cx, expr, ex, arms, source);
1073+
significant_drop_in_scrutinee::check_match(cx, expr, ex, &arms, source);
10741074
}
10751075

1076-
collapsible_match::check_match(cx, arms, self.msrv);
1076+
collapsible_match::check_match(cx, &arms, self.msrv);
10771077
if !from_expansion {
10781078
// These don't depend on a relationship between multiple arms
1079-
match_wild_err_arm::check(cx, ex, arms);
1080-
wild_in_or_pats::check(cx, ex, arms);
1079+
match_wild_err_arm::check(cx, ex, &arms);
1080+
wild_in_or_pats::check(cx, ex, &arms);
10811081
}
10821082

10831083
if let MatchSource::TryDesugar(_) = source {
10841084
try_err::check(cx, expr, ex);
10851085
}
10861086

1087-
if !from_expansion && !contains_cfg_arm(cx, expr, ex, arms) {
1087+
if !from_expansion && !contains_cfg_arm(cx, expr, ex, &arms) {
10881088
if source == MatchSource::Normal {
10891089
if !(self.msrv.meets(cx, msrvs::MATCHES_MACRO)
1090-
&& match_like_matches::check_match(cx, expr, ex, arms))
1090+
&& match_like_matches::check_match(cx, expr, ex, &arms))
10911091
{
1092-
match_same_arms::check(cx, arms);
1092+
match_same_arms::check(cx, &arms);
10931093
}
10941094

1095-
redundant_pattern_match::check_match(cx, expr, ex, arms);
1095+
redundant_pattern_match::check_match(cx, expr, ex, &arms);
10961096
let source_map = cx.tcx.sess.source_map();
10971097
let mut match_comments = span_extract_comments(source_map, expr.span);
10981098
// We remove comments from inside arms block.
@@ -1112,26 +1112,26 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
11121112
}
11131113
// If there are still comments, it means they are outside of the arms. Tell the lint
11141114
// code about it.
1115-
single_match::check(cx, ex, arms, expr, !match_comments.is_empty());
1116-
match_bool::check(cx, ex, arms, expr);
1117-
overlapping_arms::check(cx, ex, arms);
1118-
match_wild_enum::check(cx, ex, arms);
1119-
match_as_ref::check(cx, ex, arms, expr);
1120-
needless_match::check_match(cx, ex, arms, expr);
1121-
match_str_case_mismatch::check(cx, ex, arms);
1122-
redundant_guards::check(cx, arms, self.msrv);
1115+
single_match::check(cx, ex, &arms, expr, !match_comments.is_empty());
1116+
match_bool::check(cx, ex, &arms, expr);
1117+
overlapping_arms::check(cx, ex, &arms);
1118+
match_wild_enum::check(cx, ex, &arms);
1119+
match_as_ref::check(cx, ex, &arms, expr);
1120+
needless_match::check_match(cx, ex, &arms, expr);
1121+
match_str_case_mismatch::check(cx, ex, &arms);
1122+
redundant_guards::check(cx, &arms, self.msrv);
11231123

11241124
if !is_in_const_context(cx) {
1125-
manual_unwrap_or::check_match(cx, expr, ex, arms);
1126-
manual_map::check_match(cx, expr, ex, arms);
1127-
manual_filter::check_match(cx, ex, arms, expr);
1128-
manual_ok_err::check_match(cx, expr, ex, arms);
1125+
manual_unwrap_or::check_match(cx, expr, ex, &arms, self.msrv);
1126+
manual_map::check_match(cx, expr, ex, &arms);
1127+
manual_filter::check_match(cx, ex, &arms, expr);
1128+
manual_ok_err::check_match(cx, expr, ex, &arms);
11291129
}
11301130

11311131
if self.infallible_destructuring_match_linted {
11321132
self.infallible_destructuring_match_linted = false;
11331133
} else {
1134-
match_single_binding::check(cx, ex, arms, expr);
1134+
match_single_binding::check(cx, ex, &arms, expr);
11351135
}
11361136
}
11371137
match_ref_pats::check(cx, ex, arms.iter().map(|el| el.pat), expr);
@@ -1159,6 +1159,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
11591159
if_let.let_expr,
11601160
if_let.if_then,
11611161
else_expr,
1162+
self.msrv,
11621163
);
11631164
manual_map::check_if_let(cx, expr, if_let.let_pat, if_let.let_expr, if_let.if_then, else_expr);
11641165
manual_filter::check_if_let(

clippy_utils/src/msrvs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ msrv_aliases! {
7676
1,24,0 { IS_ASCII_DIGIT }
7777
1,18,0 { HASH_MAP_RETAIN, HASH_SET_RETAIN }
7878
1,17,0 { FIELD_INIT_SHORTHAND, STATIC_IN_CONST, EXPECT_ERR }
79-
1,16,0 { STR_REPEAT }
79+
1,16,0 { STR_REPEAT, UNWRAP_OR_DEFAULT }
8080
1,15,0 { MAYBE_BOUND_IN_WHERE }
8181
1,13,0 { QUESTION_MARK_OPERATOR }
8282
}

0 commit comments

Comments
 (0)