Skip to content

Commit b380cb8

Browse files
committed
add msrv to more lints. update msrv test
1 parent 61e2e2f commit b380cb8

10 files changed

+156
-56
lines changed

clippy_lints/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10051005
store.register_early_pass(move || box redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv));
10061006
store.register_early_pass(move || box redundant_field_names::RedundantFieldNames::new(msrv));
10071007
store.register_late_pass(move || box checked_conversions::CheckedConversions::new(msrv));
1008+
store.register_late_pass(move || box mem_replace::MemReplace::new(msrv));
1009+
store.register_late_pass(move || box ranges::Ranges::new(msrv));
1010+
store.register_late_pass(move || box use_self::UseSelf::new(msrv));
1011+
store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv));
10081012

10091013
store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount);
10101014
store.register_late_pass(|| box map_clone::MapClone);
@@ -1016,7 +1020,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10161020
store.register_late_pass(|| box main_recursion::MainRecursion::default());
10171021
store.register_late_pass(|| box lifetimes::Lifetimes);
10181022
store.register_late_pass(|| box entry::HashMapPass);
1019-
store.register_late_pass(|| box ranges::Ranges);
10201023
store.register_late_pass(|| box types::Casts);
10211024
let type_complexity_threshold = conf.type_complexity_threshold;
10221025
store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold));
@@ -1061,7 +1064,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10611064
store.register_late_pass(|| box neg_multiply::NegMultiply);
10621065
store.register_late_pass(|| box mem_discriminant::MemDiscriminant);
10631066
store.register_late_pass(|| box mem_forget::MemForget);
1064-
store.register_late_pass(|| box mem_replace::MemReplace);
10651067
store.register_late_pass(|| box arithmetic::Arithmetic::default());
10661068
store.register_late_pass(|| box assign_ops::AssignOps);
10671069
store.register_late_pass(|| box let_if_seq::LetIfSeq);
@@ -1083,7 +1085,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10831085
store.register_late_pass(move || box pass_by_ref_or_value);
10841086
store.register_late_pass(|| box ref_option_ref::RefOptionRef);
10851087
store.register_late_pass(|| box try_err::TryErr);
1086-
store.register_late_pass(|| box use_self::UseSelf);
10871088
store.register_late_pass(|| box bytecount::ByteCount);
10881089
store.register_late_pass(|| box infinite_iter::InfiniteIter);
10891090
store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody);
@@ -1109,7 +1110,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11091110
store.register_late_pass(|| box unnecessary_wraps::UnnecessaryWraps);
11101111
store.register_late_pass(|| box types::RefToMut);
11111112
store.register_late_pass(|| box assertions_on_constants::AssertionsOnConstants);
1112-
store.register_late_pass(|| box missing_const_for_fn::MissingConstForFn);
11131113
store.register_late_pass(|| box transmuting_null::TransmutingNull);
11141114
store.register_late_pass(|| box path_buf_push_overwrite::PathBufPushOverwrite);
11151115
store.register_late_pass(|| box integer_division::IntegerDivision);

clippy_lints/src/mem_replace.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
use crate::utils::{
22
in_macro, match_def_path, match_qpath, paths, snippet, snippet_with_applicability, span_lint_and_help,
3-
span_lint_and_sugg, span_lint_and_then,
3+
span_lint_and_sugg, span_lint_and_then, meets_msrv
44
};
55
use if_chain::if_chain;
66
use rustc_errors::Applicability;
77
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath};
8-
use rustc_lint::{LateContext, LateLintPass};
8+
use rustc_lint::{LintContext, LateContext, LateLintPass};
99
use rustc_middle::lint::in_external_macro;
10-
use rustc_session::{declare_lint_pass, declare_tool_lint};
10+
use rustc_semver::RustcVersion;
11+
use rustc_session::{impl_lint_pass, declare_tool_lint};
1112
use rustc_span::source_map::Span;
1213
use rustc_span::symbol::sym;
1314

@@ -94,7 +95,7 @@ declare_clippy_lint! {
9495
"replacing a value of type `T` with `T::default()` instead of using `std::mem::take`"
9596
}
9697

97-
declare_lint_pass!(MemReplace =>
98+
impl_lint_pass!(MemReplace =>
9899
[MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]);
99100

100101
fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
@@ -224,6 +225,19 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
224225
}
225226
}
226227

228+
const MEM_REPLACE_WITH_DEFAULT_MSRV: RustcVersion = RustcVersion::new(1, 40, 0);
229+
230+
pub struct MemReplace {
231+
msrv: Option<RustcVersion>,
232+
}
233+
234+
impl MemReplace {
235+
#[must_use]
236+
pub fn new(msrv: Option<RustcVersion>) -> Self {
237+
Self { msrv }
238+
}
239+
}
240+
227241
impl<'tcx> LateLintPass<'tcx> for MemReplace {
228242
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
229243
if_chain! {
@@ -236,8 +250,11 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace {
236250
then {
237251
check_replace_option_with_none(cx, src, dest, expr.span);
238252
check_replace_with_uninit(cx, src, dest, expr.span);
239-
check_replace_with_default(cx, src, dest, expr.span);
253+
if meets_msrv(self.msrv.as_ref(), &MEM_REPLACE_WITH_DEFAULT_MSRV) {
254+
check_replace_with_default(cx, src, dest, expr.span);
255+
}
240256
}
241257
}
242258
}
259+
extract_msrv_attr!(LateContext);
243260
}

clippy_lints/src/methods/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,7 +1487,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
14871487
["expect", ..] => lint_expect(cx, expr, arg_lists[0]),
14881488
["unwrap_or", "map"] => option_map_unwrap_or::lint(cx, expr, arg_lists[1], arg_lists[0], method_spans[1]),
14891489
["unwrap_or_else", "map"] => {
1490-
if !lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0]) {
1490+
if !lint_map_unwrap_or_else(cx, expr, arg_lists[1], arg_lists[0], self.msrv.as_ref()) {
14911491
unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "unwrap_or");
14921492
}
14931493
},
@@ -2733,14 +2733,20 @@ fn lint_map_flatten<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, map
27332733
}
27342734
}
27352735

2736+
const MAP_UNWRAP_OR_MSRV: RustcVersion = RustcVersion::new(1, 41, 0);
2737+
27362738
/// lint use of `map().unwrap_or_else()` for `Option`s and `Result`s
27372739
/// Return true if lint triggered
27382740
fn lint_map_unwrap_or_else<'tcx>(
27392741
cx: &LateContext<'tcx>,
27402742
expr: &'tcx hir::Expr<'_>,
27412743
map_args: &'tcx [hir::Expr<'_>],
27422744
unwrap_args: &'tcx [hir::Expr<'_>],
2745+
msrv: Option<&RustcVersion>
27432746
) -> bool {
2747+
if !meets_msrv(msrv, &MAP_UNWRAP_OR_MSRV) {
2748+
return false;
2749+
}
27442750
// lint if the caller of `map()` is an `Option`
27452751
let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::option_type);
27462752
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(&map_args[0]), sym::result_type);
@@ -2928,7 +2934,6 @@ const FILTER_MAP_NEXT_MSRV: RustcVersion = RustcVersion::new(1, 30, 0);
29282934
/// lint use of `filter_map().next()` for `Iterators`
29292935
fn lint_filter_map_next<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, filter_args: &'tcx [hir::Expr<'_>], msrv: Option<&RustcVersion>) {
29302936
if match_trait_method(cx, expr, &paths::ITERATOR) {
2931-
29322937
if !meets_msrv(msrv, &FILTER_MAP_NEXT_MSRV) {
29332938
return;
29342939
}

clippy_lints/src/missing_const_for_fn.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
use crate::utils::qualify_min_const_fn::is_min_const_fn;
2-
use crate::utils::{fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method};
2+
use crate::utils::{meets_msrv, fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method};
33
use rustc_hir as hir;
44
use rustc_hir::intravisit::FnKind;
55
use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
6-
use rustc_lint::{LateContext, LateLintPass};
6+
use rustc_lint::{LintContext, LateContext, LateLintPass};
77
use rustc_middle::lint::in_external_macro;
8-
use rustc_session::{declare_lint_pass, declare_tool_lint};
8+
use rustc_semver::RustcVersion;
9+
use rustc_session::{impl_lint_pass, declare_tool_lint};
910
use rustc_span::Span;
1011
use rustc_typeck::hir_ty_to_ty;
1112

13+
const MISSING_CONST_FOR_FN_MSRV: RustcVersion = RustcVersion::new(1, 37, 0);
14+
1215
declare_clippy_lint! {
1316
/// **What it does:**
1417
///
@@ -69,7 +72,18 @@ declare_clippy_lint! {
6972
"Lint functions definitions that could be made `const fn`"
7073
}
7174

72-
declare_lint_pass!(MissingConstForFn => [MISSING_CONST_FOR_FN]);
75+
impl_lint_pass!(MissingConstForFn => [MISSING_CONST_FOR_FN]);
76+
77+
pub struct MissingConstForFn {
78+
msrv: Option<RustcVersion>,
79+
}
80+
81+
impl MissingConstForFn {
82+
#[must_use]
83+
pub fn new(msrv: Option<RustcVersion>) -> Self {
84+
Self { msrv }
85+
}
86+
}
7387

7488
impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
7589
fn check_fn(
@@ -81,6 +95,10 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
8195
span: Span,
8296
hir_id: HirId,
8397
) {
98+
if !meets_msrv(self.msrv.as_ref(), &MISSING_CONST_FOR_FN_MSRV) {
99+
return;
100+
}
101+
84102
let def_id = cx.tcx.hir().local_def_id(hir_id);
85103

86104
if in_external_macro(cx.tcx.sess, span) || is_entrypoint_fn(cx, def_id.to_def_id()) {
@@ -126,6 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
126144
span_lint(cx, MISSING_CONST_FOR_FN, span, "this could be a `const fn`");
127145
}
128146
}
147+
extract_msrv_attr!(LateContext);
129148
}
130149

131150
/// Returns true if any of the method parameters is a type that implements `Drop`. The method

clippy_lints/src/ranges.rs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ use if_chain::if_chain;
33
use rustc_ast::ast::RangeLimits;
44
use rustc_errors::Applicability;
55
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, QPath};
6-
use rustc_lint::{LateContext, LateLintPass};
6+
use rustc_lint::{LintContext, LateContext, LateLintPass};
77
use rustc_middle::ty;
8-
use rustc_session::{declare_lint_pass, declare_tool_lint};
8+
use rustc_semver::RustcVersion;
9+
use rustc_session::{impl_lint_pass, declare_tool_lint};
910
use rustc_span::source_map::{Span, Spanned};
1011
use rustc_span::sym;
1112
use rustc_span::symbol::Ident;
@@ -14,7 +15,7 @@ use std::cmp::Ordering;
1415
use crate::utils::sugg::Sugg;
1516
use crate::utils::{
1617
get_parent_expr, is_integer_const, single_segment_path, snippet, snippet_opt, snippet_with_applicability,
17-
span_lint, span_lint_and_sugg, span_lint_and_then,
18+
span_lint, span_lint_and_sugg, span_lint_and_then, meets_msrv
1819
};
1920
use crate::utils::{higher, SpanlessEq};
2021

@@ -160,7 +161,20 @@ declare_clippy_lint! {
160161
"manually reimplementing {`Range`, `RangeInclusive`}`::contains`"
161162
}
162163

163-
declare_lint_pass!(Ranges => [
164+
const MANUAL_RANGE_CONTAINS_MSRV: RustcVersion = RustcVersion::new(1, 35, 0);
165+
166+
pub struct Ranges {
167+
msrv: Option<RustcVersion>,
168+
}
169+
170+
impl Ranges {
171+
#[must_use]
172+
pub fn new(msrv: Option<RustcVersion>) -> Self {
173+
Self { msrv }
174+
}
175+
}
176+
177+
impl_lint_pass!(Ranges => [
164178
RANGE_ZIP_WITH_LEN,
165179
RANGE_PLUS_ONE,
166180
RANGE_MINUS_ONE,
@@ -175,7 +189,9 @@ impl<'tcx> LateLintPass<'tcx> for Ranges {
175189
check_range_zip_with_len(cx, path, args, expr.span);
176190
},
177191
ExprKind::Binary(ref op, ref l, ref r) => {
178-
check_possible_range_contains(cx, op.node, l, r, expr.span);
192+
if meets_msrv(self.msrv.as_ref(), &MANUAL_RANGE_CONTAINS_MSRV) {
193+
check_possible_range_contains(cx, op.node, l, r, expr.span);
194+
}
179195
},
180196
_ => {},
181197
}
@@ -184,6 +200,7 @@ impl<'tcx> LateLintPass<'tcx> for Ranges {
184200
check_inclusive_range_minus_one(cx, expr);
185201
check_reversed_empty_range(cx, expr);
186202
}
203+
extract_msrv_attr!(LateContext);
187204
}
188205

189206
fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'_>, r: &Expr<'_>, span: Span) {

clippy_lints/src/redundant_field_names.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ impl_lint_pass!(RedundantFieldNames => [REDUNDANT_FIELD_NAMES]);
5151

5252
impl EarlyLintPass for RedundantFieldNames {
5353
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
54-
5554
if !meets_msrv(self.msrv.as_ref(), &REDUNDANT_FIELD_NAMES_MSRV) {
5655
return;
5756
}
@@ -83,6 +82,5 @@ impl EarlyLintPass for RedundantFieldNames {
8382
}
8483
}
8584
}
86-
8785
extract_msrv_attr!(EarlyContext);
8886
}

clippy_lints/src/redundant_static_lifetimes.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ impl RedundantStaticLifetimes {
9898

9999
impl EarlyLintPass for RedundantStaticLifetimes {
100100
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
101-
102101
if !meets_msrv(self.msrv.as_ref(), &REDUNDANT_STATIC_LIFETIMES_MSRV) {
103102
return;
104103
}

clippy_lints/src/use_self.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ use rustc_middle::hir::map::Map;
1212
use rustc_middle::lint::in_external_macro;
1313
use rustc_middle::ty;
1414
use rustc_middle::ty::{DefIdTree, Ty};
15-
use rustc_session::{declare_lint_pass, declare_tool_lint};
15+
use rustc_semver::RustcVersion;
16+
use rustc_session::{impl_lint_pass, declare_tool_lint};
1617
use rustc_span::symbol::kw;
1718
use rustc_typeck::hir_ty_to_ty;
1819

19-
use crate::utils::{differing_macro_contexts, span_lint_and_sugg};
20+
use crate::utils::{meets_msrv, differing_macro_contexts, span_lint_and_sugg};
2021

2122
declare_clippy_lint! {
2223
/// **What it does:** Checks for unnecessary repetition of structure name when a
@@ -53,7 +54,7 @@ declare_clippy_lint! {
5354
"unnecessary structure name repetition whereas `Self` is applicable"
5455
}
5556

56-
declare_lint_pass!(UseSelf => [USE_SELF]);
57+
impl_lint_pass!(UseSelf => [USE_SELF]);
5758

5859
const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element";
5960

@@ -157,8 +158,25 @@ fn check_trait_method_impl_decl<'tcx>(
157158
}
158159
}
159160

161+
const USE_SELF_MSRV: RustcVersion = RustcVersion::new(1, 37, 0);
162+
163+
pub struct UseSelf {
164+
msrv: Option<RustcVersion>,
165+
}
166+
167+
impl UseSelf {
168+
#[must_use]
169+
pub fn new(msrv: Option<RustcVersion>) -> Self {
170+
Self { msrv }
171+
}
172+
}
173+
160174
impl<'tcx> LateLintPass<'tcx> for UseSelf {
161175
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
176+
if !meets_msrv(self.msrv.as_ref(), &USE_SELF_MSRV) {
177+
return;
178+
}
179+
162180
if in_external_macro(cx.sess(), item.span) {
163181
return;
164182
}
@@ -204,6 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
204222
}
205223
}
206224
}
225+
extract_msrv_attr!(LateContext);
207226
}
208227

209228
struct UseSelfVisitor<'a, 'tcx> {

tests/ui/min_rust_version_attr.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,37 @@ pub fn filter_map_next() {
7373
.next();
7474
}
7575

76+
pub fn manual_range_contains() {
77+
x >= 8 && x < 12;
78+
}
79+
80+
pub fn use_self() {
81+
struct Foo {}
82+
83+
impl Foo {
84+
fn new() -> Foo {
85+
Foo {}
86+
}
87+
fn test() -> Foo {
88+
Foo::new()
89+
}
90+
}
91+
}
92+
93+
fn replace_with_default() {
94+
let mut s = String::from("foo");
95+
let _ = std::mem::replace(s, String::default());
96+
}
97+
98+
fn map_unwrap_or() {
99+
let opt = Some(1);
100+
101+
// Check for `option.map(_).unwrap_or(_)` use.
102+
// Single line case.
103+
let _ = opt.map(|x| x + 1)
104+
// Should lint even though this call is on a separate line.
105+
.unwrap_or(0);
106+
}
76107

77108
fn main() {
78109
filter_map_next();
@@ -84,6 +115,10 @@ fn main() {
84115
match_same_arms();
85116
match_same_arms2();
86117
manual_strip_msrv();
118+
manual_range_contains();
119+
use_self();
120+
replace_with_default();
121+
map_unwrap_or();
87122
}
88123

89124
mod meets_msrv {

0 commit comments

Comments
 (0)