Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for minimum supported rust version #6201

Merged
merged 4 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ extern crate rustc_target;
extern crate rustc_trait_selection;
extern crate rustc_typeck;

use crate::utils::parse_msrv;
use rustc_data_structures::fx::FxHashSet;
use rustc_lint::LintId;
use rustc_session::Session;
Expand Down Expand Up @@ -933,7 +934,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&zero_div_zero::ZERO_DIVIDED_BY_ZERO,
]);
// end register lints, do not remove this comment, it’s used in `update_lints`

store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
store.register_late_pass(|| box serde_api::SerdeAPI);
store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
Expand Down Expand Up @@ -969,7 +969,23 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box strings::StringAdd);
store.register_late_pass(|| box implicit_return::ImplicitReturn);
store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
store.register_late_pass(|| box methods::Methods);

let parsed_msrv = conf.msrv.as_ref().and_then(|s| {
parse_msrv(s, None, None).or_else(|| {
sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
None
})
});

flip1995 marked this conversation as resolved.
Show resolved Hide resolved
let msrv = parsed_msrv.clone();
store.register_late_pass(move || box methods::Methods::new(msrv.clone()));
let msrv = parsed_msrv.clone();
store.register_late_pass(move || box matches::Matches::new(msrv.clone()));
let msrv = parsed_msrv.clone();
store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv.clone()));
let msrv = parsed_msrv;
store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv.clone()));

store.register_late_pass(|| box map_clone::MapClone);
store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
store.register_late_pass(|| box shadow::Shadow);
Expand All @@ -983,7 +999,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box types::Casts);
let type_complexity_threshold = conf.type_complexity_threshold;
store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold));
store.register_late_pass(|| box matches::Matches::default());
store.register_late_pass(|| box minmax::MinMaxPass);
store.register_late_pass(|| box open_options::OpenOptions);
store.register_late_pass(|| box zero_div_zero::ZeroDiv);
Expand Down Expand Up @@ -1144,7 +1159,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box if_let_mutex::IfLetMutex);
store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive);
store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
store.register_early_pass(|| box redundant_field_names::RedundantFieldNames);
store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
Expand All @@ -1166,7 +1180,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|| box manual_ok_or::ManualOkOr);
store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
store.register_late_pass(|| box manual_strip::ManualStrip);
store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
Expand Down
33 changes: 30 additions & 3 deletions clippy_lints/src/manual_non_exhaustive.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
use crate::utils::{snippet_opt, span_lint_and_then};
use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then};
use if_chain::if_chain;
use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind};
use rustc_attr as attr;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span};
use semver::{Version, VersionReq};

const MANUAL_NON_EXHAUSTIVE_MSRV: Version = Version {
major: 1,
minor: 40,
patch: 0,
pre: Vec::new(),
build: Vec::new(),
};

flip1995 marked this conversation as resolved.
Show resolved Hide resolved
declare_clippy_lint! {
/// **What it does:** Checks for manual implementations of the non-exhaustive pattern.
Expand Down Expand Up @@ -55,10 +64,26 @@ declare_clippy_lint! {
"manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]"
}

declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
#[derive(Clone)]
pub struct ManualNonExhaustive {
msrv: Option<VersionReq>,
}

impl ManualNonExhaustive {
#[must_use]
pub fn new(msrv: Option<VersionReq>) -> Self {
Self { msrv }
}
}

impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);

impl EarlyLintPass for ManualNonExhaustive {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if !meets_msrv(self.msrv.as_ref(), &MANUAL_NON_EXHAUSTIVE_MSRV) {
return;
flip1995 marked this conversation as resolved.
Show resolved Hide resolved
}

match &item.kind {
ItemKind::Enum(def, _) => {
check_manual_non_exhaustive_enum(cx, item, &def.variants);
Expand All @@ -73,6 +98,8 @@ impl EarlyLintPass for ManualNonExhaustive {
_ => {},
}
}

extract_msrv_attr!(EarlyContext);
}

fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) {
Expand Down
34 changes: 30 additions & 4 deletions clippy_lints/src/manual_strip.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::consts::{constant, Constant};
use crate::utils::usage::mutated_variables;
use crate::utils::{
eq_expr_value, higher, match_def_path, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
};

use if_chain::if_chain;
Expand All @@ -10,12 +10,21 @@ use rustc_hir::def::Res;
use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc_hir::BinOpKind;
use rustc_hir::{BorrowKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Spanned;
use rustc_span::Span;
use semver::{Version, VersionReq};

const MANUAL_STRIP_MSRV: Version = Version {
major: 1,
minor: 45,
patch: 0,
pre: Vec::new(),
build: Vec::new(),
};

declare_clippy_lint! {
/// **What it does:**
Expand Down Expand Up @@ -51,7 +60,18 @@ declare_clippy_lint! {
"suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing"
}

declare_lint_pass!(ManualStrip => [MANUAL_STRIP]);
pub struct ManualStrip {
msrv: Option<VersionReq>,
}

impl ManualStrip {
#[must_use]
pub fn new(msrv: Option<VersionReq>) -> Self {
Self { msrv }
}
}

impl_lint_pass!(ManualStrip => [MANUAL_STRIP]);

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
enum StripKind {
Expand All @@ -61,6 +81,10 @@ enum StripKind {

impl<'tcx> LateLintPass<'tcx> for ManualStrip {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) {
return;
flip1995 marked this conversation as resolved.
Show resolved Hide resolved
}

if_chain! {
if let Some((cond, then, _)) = higher::if_block(&expr);
if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind;
Expand Down Expand Up @@ -114,6 +138,8 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
}
}
}

extract_msrv_attr!(LateContext);
}

// Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
Expand Down
33 changes: 30 additions & 3 deletions clippy_lints/src/matches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ use crate::utils::sugg::Sugg;
use crate::utils::usage::is_unused;
use crate::utils::{
expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable,
is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet,
snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, meets_msrv, multispan_sugg, remove_blocks,
snippet, snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
span_lint_and_then,
};
use crate::utils::{paths, search_same, SpanlessEq, SpanlessHash};
Expand All @@ -23,6 +23,7 @@ use rustc_middle::ty::{self, Ty, TyS};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::{Span, Spanned};
use rustc_span::{sym, Symbol};
use semver::{Version, VersionReq};
use std::cmp::Ordering;
use std::collections::hash_map::Entry;
use std::collections::Bound;
Expand Down Expand Up @@ -527,9 +528,20 @@ declare_clippy_lint! {

#[derive(Default)]
pub struct Matches {
msrv: Option<VersionReq>,
infallible_destructuring_match_linted: bool,
}

impl Matches {
#[must_use]
pub fn new(msrv: Option<VersionReq>) -> Self {
Self {
msrv,
..Matches::default()
}
}
}

impl_lint_pass!(Matches => [
SINGLE_MATCH,
MATCH_REF_PATS,
Expand All @@ -549,14 +561,27 @@ impl_lint_pass!(Matches => [
MATCH_SAME_ARMS,
]);

const MATCH_LIKE_MATCHES_MACRO_MSRV: Version = Version {
major: 1,
minor: 42,
patch: 0,
pre: Vec::new(),
build: Vec::new(),
};

impl<'tcx> LateLintPass<'tcx> for Matches {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if in_external_macro(cx.sess(), expr.span) || in_macro(expr.span) {
return;
}

redundant_pattern_match::check(cx, expr);
if !check_match_like_matches(cx, expr) {

if meets_msrv(self.msrv.as_ref(), &MATCH_LIKE_MATCHES_MACRO_MSRV) {
if !check_match_like_matches(cx, expr) {
lint_match_arms(cx, expr);
}
} else {
lint_match_arms(cx, expr);
}

Expand Down Expand Up @@ -640,6 +665,8 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
}
}
}

extract_msrv_attr!(LateContext);
}

#[rustfmt::skip]
Expand Down
43 changes: 37 additions & 6 deletions clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, TraitRef, Ty, TyS};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::symbol::{sym, SymbolStr};

Expand All @@ -30,10 +30,11 @@ use crate::utils::usage::mutated_variables;
use crate::utils::{
contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro,
is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath,
match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty,
single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
match_trait_method, match_type, match_var, meets_msrv, method_calls, method_chain_args, paths, remove_blocks,
return_ty, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth, SpanlessEq,
};
use semver::{Version, VersionReq};

declare_clippy_lint! {
/// **What it does:** Checks for `.unwrap()` calls on `Option`s and on `Result`s.
Expand Down Expand Up @@ -1404,7 +1405,18 @@ declare_clippy_lint! {
"use `.collect()` instead of `::from_iter()`"
}

declare_lint_pass!(Methods => [
pub struct Methods {
msrv: Option<VersionReq>,
}

impl Methods {
#[must_use]
pub fn new(msrv: Option<VersionReq>) -> Self {
Self { msrv }
}
}

impl_lint_pass!(Methods => [
UNWRAP_USED,
EXPECT_USED,
SHOULD_IMPLEMENT_TRAIT,
Expand Down Expand Up @@ -1531,8 +1543,12 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
check_pointer_offset(cx, expr, arg_lists[0])
},
["is_file", ..] => lint_filetype_is_file(cx, expr, arg_lists[0]),
["map", "as_ref"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false),
["map", "as_mut"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true),
["map", "as_ref"] => {
lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false, self.msrv.as_ref())
},
["map", "as_mut"] => {
lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true, self.msrv.as_ref())
},
["unwrap_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "unwrap_or"),
["get_or_insert_with", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "get_or_insert"),
["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "ok_or"),
Expand Down Expand Up @@ -1738,6 +1754,8 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
}
}
}

extract_msrv_attr!(LateContext);
}

/// Checks for the `OR_FUN_CALL` lint.
Expand Down Expand Up @@ -3453,14 +3471,27 @@ fn lint_suspicious_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
);
}

const OPTION_AS_REF_DEREF_MSRV: Version = Version {
major: 1,
minor: 40,
patch: 0,
pre: Vec::new(),
build: Vec::new(),
};

flip1995 marked this conversation as resolved.
Show resolved Hide resolved
/// lint use of `_.as_ref().map(Deref::deref)` for `Option`s
fn lint_option_as_ref_deref<'tcx>(
cx: &LateContext<'tcx>,
expr: &hir::Expr<'_>,
as_ref_args: &[hir::Expr<'_>],
map_args: &[hir::Expr<'_>],
is_mut: bool,
msrv: Option<&VersionReq>,
) {
if !meets_msrv(msrv, &OPTION_AS_REF_DEREF_MSRV) {
return;
flip1995 marked this conversation as resolved.
Show resolved Hide resolved
}

let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not);

let option_ty = cx.typeck_results().expr_ty(&as_ref_args[0]);
Expand Down
Loading