Add clippy_utils::msrv::Msrv to keep track of the current MSRV

This commit is contained in:
Alex Macleod 2022-11-21 14:37:51 +00:00
parent 51ec465cc3
commit 637139d2ff
56 changed files with 466 additions and 433 deletions

View file

@ -443,22 +443,22 @@ value is passed to the constructor in `clippy_lints/lib.rs`.
```rust
pub struct ManualStrip {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ManualStrip {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
```
The project's MSRV can then be matched against the feature MSRV in the LintPass
using the `meets_msrv` utility function.
using the `Msrv::meets` method.
``` rust
if !meets_msrv(self.msrv, msrvs::STR_STRIP_PREFIX) {
if !self.msrv.meets(msrvs::STR_STRIP_PREFIX) {
return;
}
```

View file

@ -120,7 +120,7 @@ fn add_lint(lint: &LintData<'_>, enable_msrv: bool) -> io::Result<()> {
let new_lint = if enable_msrv {
format!(
"store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv)));\n ",
"store.register_{lint_pass}_pass(move |{ctor_arg}| Box::new({module_name}::{camel_name}::new(msrv())));\n ",
lint_pass = lint.pass,
ctor_arg = if lint.pass == "late" { "_" } else { "" },
module_name = lint.name,
@ -238,10 +238,9 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
result.push_str(&if enable_msrv {
formatdoc!(
r#"
use clippy_utils::msrvs;
use clippy_utils::msrvs::{{self, Msrv}};
{pass_import}
use rustc_lint::{{{context_import}, {pass_type}, LintContext}};
use rustc_semver::RustcVersion;
use rustc_session::{{declare_tool_lint, impl_lint_pass}};
"#
@ -263,12 +262,12 @@ fn get_lint_file_contents(lint: &LintData<'_>, enable_msrv: bool) -> String {
formatdoc!(
r#"
pub struct {name_camel} {{
msrv: Option<RustcVersion>,
msrv: Msrv,
}}
impl {name_camel} {{
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {{
pub fn new(msrv: Msrv) -> Self {{
Self {{ msrv }}
}}
}}
@ -357,15 +356,14 @@ fn create_lint_for_ty(lint: &LintData<'_>, enable_msrv: bool, ty: &str) -> io::R
let _ = writedoc!(
lint_file_contents,
r#"
use clippy_utils::{{meets_msrv, msrvs}};
use clippy_utils::msrvs::{{self, Msrv}};
use rustc_lint::{{{context_import}, LintContext}};
use rustc_semver::RustcVersion;
use super::{name_upper};
// TODO: Adjust the parameters as necessary
pub(super) fn check(cx: &{context_import}, msrv: Option<RustcVersion>) {{
if !meets_msrv(msrv, todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{
pub(super) fn check(cx: &{context_import}, msrv: &Msrv) {{
if !msrv.meets(todo!("Add a new entry in `clippy_utils/src/msrvs`")) {{
return;
}}
todo!();

View file

@ -1,11 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{trim_span, walk_span_to_context};
use clippy_utils::{meets_msrv, msrvs};
use rustc_ast::ast::{Expr, ExprKind, LitKind, Pat, PatKind, RangeEnd, RangeLimits};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
@ -33,10 +32,10 @@ declare_clippy_lint! {
impl_lint_pass!(AlmostCompleteLetterRange => [ALMOST_COMPLETE_LETTER_RANGE]);
pub struct AlmostCompleteLetterRange {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl AlmostCompleteLetterRange {
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -46,7 +45,7 @@ impl EarlyLintPass for AlmostCompleteLetterRange {
let ctxt = e.span.ctxt();
let sugg = if let Some(start) = walk_span_to_context(start.span, ctxt)
&& let Some(end) = walk_span_to_context(end.span, ctxt)
&& meets_msrv(self.msrv, msrvs::RANGE_INCLUSIVE)
&& self.msrv.meets(msrvs::RANGE_INCLUSIVE)
{
Some((trim_span(cx.sess().source_map(), start.between(end)), "..="))
} else {
@ -60,7 +59,7 @@ impl EarlyLintPass for AlmostCompleteLetterRange {
if let PatKind::Range(Some(start), Some(end), kind) = &p.kind
&& matches!(kind.node, RangeEnd::Excluded)
{
let sugg = if meets_msrv(self.msrv, msrvs::RANGE_INCLUSIVE) {
let sugg = if self.msrv.meets(msrvs::RANGE_INCLUSIVE) {
"..="
} else {
"..."

View file

@ -1,5 +1,5 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::{meets_msrv, msrvs};
use clippy_utils::msrvs::{self, Msrv};
use rustc_ast::ast::{FloatTy, LitFloatType, LitKind};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
@ -63,12 +63,12 @@ const KNOWN_CONSTS: [(f64, &str, usize, Option<RustcVersion>); 19] = [
];
pub struct ApproxConstant {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ApproxConstant {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
@ -87,7 +87,7 @@ impl ApproxConstant {
let s = s.as_str();
if s.parse::<f64>().is_ok() {
for &(constant, name, min_digits, msrv) in &KNOWN_CONSTS {
if is_approx_const(constant, s, min_digits) && msrv.map_or(true, |msrv| meets_msrv(self.msrv, msrv)) {
if is_approx_const(constant, s, min_digits) && msrv.map_or(true, |msrv| self.msrv.meets(msrv)) {
span_lint_and_help(
cx,
APPROX_CONSTANT,

View file

@ -2,9 +2,8 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::macros::{is_panic, macro_backtrace};
use clippy_utils::msrvs;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
use clippy_utils::{extract_msrv_attr, meets_msrv};
use if_chain::if_chain;
use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
use rustc_errors::Applicability;
@ -14,7 +13,6 @@ use rustc_hir::{
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_semver::RustcVersion;
use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::symbol::Symbol;
@ -599,7 +597,7 @@ fn is_word(nmi: &NestedMetaItem, expected: Symbol) -> bool {
}
pub struct EarlyAttributes {
pub msrv: Option<RustcVersion>,
pub msrv: Msrv,
}
impl_lint_pass!(EarlyAttributes => [
@ -614,7 +612,7 @@ impl EarlyLintPass for EarlyAttributes {
}
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
check_deprecated_cfg_attr(cx, attr, self.msrv);
check_deprecated_cfg_attr(cx, attr, &self.msrv);
check_mismatched_target_os(cx, attr);
}
@ -654,9 +652,9 @@ fn check_empty_line_after_outer_attr(cx: &EarlyContext<'_>, item: &rustc_ast::It
}
}
fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: Option<RustcVersion>) {
fn check_deprecated_cfg_attr(cx: &EarlyContext<'_>, attr: &Attribute, msrv: &Msrv) {
if_chain! {
if meets_msrv(msrv, msrvs::TOOL_ATTRIBUTES);
if msrv.meets(msrvs::TOOL_ATTRIBUTES);
// check cfg_attr
if attr.has_name(sym::cfg_attr);
if let Some(items) = attr.meta_item_list();

View file

@ -1,11 +1,10 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::sugg::Sugg;
use clippy_utils::{meets_msrv, msrvs};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
use rustc_semver::RustcVersion;
use super::CAST_ABS_TO_UNSIGNED;
@ -15,9 +14,9 @@ pub(super) fn check(
cast_expr: &Expr<'_>,
cast_from: Ty<'_>,
cast_to: Ty<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if meets_msrv(msrv, msrvs::UNSIGNED_ABS)
if msrv.meets(msrvs::UNSIGNED_ABS)
&& let ty::Int(from) = cast_from.kind()
&& let ty::Uint(to) = cast_to.kind()
&& let ExprKind::MethodCall(method_path, receiver, ..) = cast_expr.kind

View file

@ -1,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::in_constant;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_isize_or_usize;
use clippy_utils::{in_constant, meets_msrv, msrvs};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, FloatTy, Ty};
use rustc_semver::RustcVersion;
use super::{utils, CAST_LOSSLESS};
@ -16,7 +16,7 @@ pub(super) fn check(
cast_op: &Expr<'_>,
cast_from: Ty<'_>,
cast_to: Ty<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if !should_lint(cx, expr, cast_from, cast_to, msrv) {
return;
@ -57,13 +57,7 @@ pub(super) fn check(
);
}
fn should_lint(
cx: &LateContext<'_>,
expr: &Expr<'_>,
cast_from: Ty<'_>,
cast_to: Ty<'_>,
msrv: Option<RustcVersion>,
) -> bool {
fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>, msrv: &Msrv) -> bool {
// Do not suggest using From in consts/statics until it is valid to do so (see #2267).
if in_constant(cx, expr.hir_id) {
return false;
@ -89,7 +83,7 @@ fn should_lint(
};
!is_isize_or_usize(cast_from) && from_nbits < to_nbits
},
(false, true) if matches!(cast_from.kind(), ty::Bool) && meets_msrv(msrv, msrvs::FROM_BOOL) => true,
(false, true) if matches!(cast_from.kind(), ty::Bool) && msrv.meets(msrvs::FROM_BOOL) => true,
(_, _) => {
matches!(cast_from.kind(), ty::Float(FloatTy::F32)) && matches!(cast_to.kind(), ty::Float(FloatTy::F64))
},

View file

@ -1,16 +1,16 @@
use clippy_utils::{diagnostics::span_lint_and_then, meets_msrv, msrvs, source};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::{diagnostics::span_lint_and_then, source};
use if_chain::if_chain;
use rustc_ast::Mutability;
use rustc_hir::{Expr, ExprKind, Node};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, layout::LayoutOf, Ty, TypeAndMut};
use rustc_semver::RustcVersion;
use super::CAST_SLICE_DIFFERENT_SIZES;
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: Option<RustcVersion>) {
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, msrv: &Msrv) {
// suggestion is invalid if `ptr::slice_from_raw_parts` does not exist
if !meets_msrv(msrv, msrvs::PTR_SLICE_RAW_PARTS) {
if !msrv.meets(msrvs::PTR_SLICE_RAW_PARTS) {
return;
}

View file

@ -1,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{match_def_path, meets_msrv, msrvs, paths};
use clippy_utils::{match_def_path, paths};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{def_id::DefId, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty};
use rustc_semver::RustcVersion;
use super::CAST_SLICE_FROM_RAW_PARTS;
@ -25,15 +25,9 @@ fn raw_parts_kind(cx: &LateContext<'_>, did: DefId) -> Option<RawPartsKind> {
}
}
pub(super) fn check(
cx: &LateContext<'_>,
expr: &Expr<'_>,
cast_expr: &Expr<'_>,
cast_to: Ty<'_>,
msrv: Option<RustcVersion>,
) {
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to: Ty<'_>, msrv: &Msrv) {
if_chain! {
if meets_msrv(msrv, msrvs::PTR_SLICE_RAW_PARTS);
if msrv.meets(msrvs::PTR_SLICE_RAW_PARTS);
if let ty::RawPtr(ptrty) = cast_to.kind();
if let ty::Slice(_) = ptrty.ty.kind();
if let ExprKind::Call(fun, [ptr_arg, len_arg]) = cast_expr.peel_blocks().kind;

View file

@ -21,11 +21,11 @@ mod ptr_as_ptr;
mod unnecessary_cast;
mod utils;
use clippy_utils::{is_hir_ty_cfg_dependant, meets_msrv, msrvs};
use clippy_utils::is_hir_ty_cfg_dependant;
use clippy_utils::msrvs::{self, Msrv};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! {
@ -648,12 +648,12 @@ declare_clippy_lint! {
}
pub struct Casts {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl Casts {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -686,7 +686,7 @@ impl_lint_pass!(Casts => [
impl<'tcx> LateLintPass<'tcx> for Casts {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if !in_external_macro(cx.sess(), expr.span) {
ptr_as_ptr::check(cx, expr, self.msrv);
ptr_as_ptr::check(cx, expr, &self.msrv);
}
if expr.span.from_expansion() {
@ -705,7 +705,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
if unnecessary_cast::check(cx, expr, cast_expr, cast_from, cast_to) {
return;
}
cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, self.msrv);
cast_slice_from_raw_parts::check(cx, expr, cast_expr, cast_to, &self.msrv);
as_ptr_cast_mut::check(cx, expr, cast_expr, cast_to);
fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to);
fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
@ -717,16 +717,16 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
cast_precision_loss::check(cx, expr, cast_from, cast_to);
cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv);
cast_abs_to_unsigned::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
cast_nan_to_int::check(cx, expr, cast_expr, cast_from, cast_to);
}
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, self.msrv);
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to, &self.msrv);
cast_enum_constructor::check(cx, expr, cast_expr, cast_from);
}
as_underscore::check(cx, expr, cast_to_hir);
if meets_msrv(self.msrv, msrvs::BORROW_AS_PTR) {
if self.msrv.meets(msrvs::BORROW_AS_PTR) {
borrow_as_ptr::check(cx, expr, cast_expr, cast_to_hir);
}
}
@ -734,8 +734,8 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
cast_ref_to_mut::check(cx, expr);
cast_ptr_alignment::check(cx, expr);
char_lit_as_u8::check(cx, expr);
ptr_as_ptr::check(cx, expr, self.msrv);
cast_slice_different_sizes::check(cx, expr, self.msrv);
ptr_as_ptr::check(cx, expr, &self.msrv);
cast_slice_different_sizes::check(cx, expr, &self.msrv);
}
extract_msrv_attr!(LateContext);

View file

@ -1,19 +1,18 @@
use std::borrow::Cow;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::sugg::Sugg;
use clippy_utils::{meets_msrv, msrvs};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, Mutability, TyKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, TypeAndMut};
use rustc_semver::RustcVersion;
use super::PTR_AS_PTR;
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Option<RustcVersion>) {
if !meets_msrv(msrv, msrvs::POINTER_CAST) {
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: &Msrv) {
if !msrv.meets(msrvs::POINTER_CAST) {
return;
}

View file

@ -1,14 +1,14 @@
//! lint on manually implemented checked conversions that could be transformed into `try_from`
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{in_constant, is_integer_literal, meets_msrv, msrvs, SpanlessEq};
use clippy_utils::{in_constant, is_integer_literal, SpanlessEq};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! {
@ -37,12 +37,12 @@ declare_clippy_lint! {
}
pub struct CheckedConversions {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl CheckedConversions {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -51,7 +51,7 @@ impl_lint_pass!(CheckedConversions => [CHECKED_CONVERSIONS]);
impl<'tcx> LateLintPass<'tcx> for CheckedConversions {
fn check_expr(&mut self, cx: &LateContext<'_>, item: &Expr<'_>) {
if !meets_msrv(self.msrv, msrvs::TRY_FROM) {
if !self.msrv.meets(msrvs::TRY_FROM) {
return;
}

View file

@ -1,12 +1,13 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_hir_and_then};
use clippy_utils::mir::{enclosing_mir, expr_local, local_assignments, used_exactly_once, PossibleBorrowerMap};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
use clippy_utils::sugg::has_enclosing_paren;
use clippy_utils::ty::{expr_sig, is_copy, peel_mid_ty_refs, ty_sig, variant_of_res};
use clippy_utils::{
fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, meets_msrv, msrvs, path_to_local,
walk_to_expr_usage,
fn_def_id, get_parent_expr, get_parent_expr_for_hir, is_lint_allowed, path_to_local, walk_to_expr_usage,
};
use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::graph::iterate::{CycleDetector, TriColorDepthFirstSearch};
@ -28,7 +29,6 @@ use rustc_middle::ty::{
self, Binder, BoundVariableKind, EarlyBinder, FnSig, GenericArgKind, List, ParamTy, PredicateKind,
ProjectionPredicate, Ty, TyCtxt, TypeVisitable, TypeckResults,
};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span, Symbol, DUMMY_SP};
use rustc_trait_selection::infer::InferCtxtExt as _;
@ -181,12 +181,12 @@ pub struct Dereferencing<'tcx> {
possible_borrowers: Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
// `IntoIterator` for arrays requires Rust 1.53.
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl<'tcx> Dereferencing<'tcx> {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self {
msrv,
..Dereferencing::default()
@ -286,7 +286,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> {
match (self.state.take(), kind) {
(None, kind) => {
let expr_ty = typeck.expr_ty(expr);
let (position, adjustments) = walk_parents(cx, &mut self.possible_borrowers, expr, self.msrv);
let (position, adjustments) = walk_parents(cx, &mut self.possible_borrowers, expr, &self.msrv);
match kind {
RefOp::Deref => {
if let Position::FieldAccess {
@ -698,7 +698,7 @@ fn walk_parents<'tcx>(
cx: &LateContext<'tcx>,
possible_borrowers: &mut Vec<(LocalDefId, PossibleBorrowerMap<'tcx, 'tcx>)>,
e: &'tcx Expr<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) -> (Position, &'tcx [Adjustment<'tcx>]) {
let mut adjustments = [].as_slice();
let mut precedence = 0i8;
@ -1082,7 +1082,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
param_ty: ParamTy,
mut expr: &Expr<'tcx>,
precedence: i8,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) -> Position {
let destruct_trait_def_id = cx.tcx.lang_items().destruct_trait();
let sized_trait_def_id = cx.tcx.lang_items().sized_trait();
@ -1182,7 +1182,7 @@ fn needless_borrow_impl_arg_position<'tcx>(
&& let ty::Param(param_ty) = trait_predicate.self_ty().kind()
&& let GenericArgKind::Type(ty) = substs_with_referent_ty[param_ty.index as usize].unpack()
&& ty.is_array()
&& !meets_msrv(msrv, msrvs::ARRAY_INTO_ITERATOR)
&& !msrv.meets(msrvs::ARRAY_INTO_ITERATOR)
{
return false;
}

View file

@ -1,11 +1,12 @@
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::is_diag_trait_item;
use clippy_utils::macros::FormatParamKind::{Implicit, Named, Numbered, Starred};
use clippy_utils::macros::{
is_format_macro, is_panic, root_macro_call, Count, FormatArg, FormatArgsExpn, FormatParam, FormatParamUsage,
};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{is_diag_trait_item, meets_msrv, msrvs};
use if_chain::if_chain;
use itertools::Itertools;
use rustc_errors::Applicability;
@ -13,7 +14,6 @@ use rustc_hir::{Expr, ExprKind, HirId, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::Ty;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::def_id::DefId;
use rustc_span::edition::Edition::Edition2021;
@ -158,12 +158,12 @@ impl_lint_pass!(FormatArgs => [
]);
pub struct FormatArgs {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl FormatArgs {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -188,7 +188,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs {
check_format_in_format_args(cx, outermost_expn_data.call_site, name, arg.param.value);
check_to_string_in_format_args(cx, name, arg.param.value);
}
if meets_msrv(self.msrv, msrvs::FORMAT_ARGS_CAPTURE) {
if self.msrv.meets(msrvs::FORMAT_ARGS_CAPTURE) {
check_uninlined_args(cx, &format_args, outermost_expn_data.call_site, macro_def_id);
}
}

View file

@ -1,7 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::macros::span_is_local;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::path_def_id;
use clippy_utils::source::snippet_opt;
use clippy_utils::{meets_msrv, msrvs, path_def_id};
use rustc_errors::Applicability;
use rustc_hir::intravisit::{walk_path, Visitor};
use rustc_hir::{
@ -10,7 +11,6 @@ use rustc_hir::{
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::{kw, sym};
use rustc_span::{Span, Symbol};
@ -49,12 +49,12 @@ declare_clippy_lint! {
}
pub struct FromOverInto {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl FromOverInto {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
FromOverInto { msrv }
}
}
@ -63,7 +63,7 @@ impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]);
impl<'tcx> LateLintPass<'tcx> for FromOverInto {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
if !meets_msrv(self.msrv, msrvs::RE_REBALANCING_COHERENCE) || !span_is_local(item.span) {
if !self.msrv.meets(msrvs::RE_REBALANCING_COHERENCE) || !span_is_local(item.span) {
return;
}

View file

@ -1,14 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_macro_callsite;
use clippy_utils::{
contains_return, higher, is_else_clause, is_res_lang_ctor, meets_msrv, msrvs, path_res, peel_blocks,
};
use clippy_utils::{contains_return, higher, is_else_clause, is_res_lang_ctor, path_res, peel_blocks};
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! {
@ -47,12 +45,12 @@ declare_clippy_lint! {
}
pub struct IfThenSomeElseNone {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl IfThenSomeElseNone {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -61,7 +59,7 @@ impl_lint_pass!(IfThenSomeElseNone => [IF_THEN_SOME_ELSE_NONE]);
impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if !meets_msrv(self.msrv, msrvs::BOOL_THEN) {
if !self.msrv.meets(msrvs::BOOL_THEN) {
return;
}
@ -94,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
} else {
format!("{{ /* snippet */ {arg_snip} }}")
};
let method_name = if switch_to_eager_eval(cx, expr) && meets_msrv(self.msrv, msrvs::BOOL_THEN_SOME) {
let method_name = if switch_to_eager_eval(cx, expr) && self.msrv.meets(msrvs::BOOL_THEN_SOME) {
"then_some"
} else {
method_body.insert_str(0, "|| ");

View file

@ -1,8 +1,9 @@
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLet;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::is_copy;
use clippy_utils::{is_expn_of, is_lint_allowed, meets_msrv, msrvs, path_to_local};
use clippy_utils::{is_expn_of, is_lint_allowed, path_to_local};
use if_chain::if_chain;
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
use rustc_errors::Applicability;
@ -11,7 +12,6 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::nested_filter;
use rustc_middle::ty;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::Ident, Span};
@ -51,14 +51,13 @@ declare_clippy_lint! {
"avoid indexing on slices which could be destructed"
}
#[derive(Copy, Clone)]
pub struct IndexRefutableSlice {
max_suggested_slice: u64,
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl IndexRefutableSlice {
pub fn new(max_suggested_slice_pattern_length: u64, msrv: Option<RustcVersion>) -> Self {
pub fn new(max_suggested_slice_pattern_length: u64, msrv: Msrv) -> Self {
Self {
max_suggested_slice: max_suggested_slice_pattern_length,
msrv,
@ -74,7 +73,7 @@ impl<'tcx> LateLintPass<'tcx> for IndexRefutableSlice {
if !expr.span.from_expansion() || is_expn_of(expr.span, "if_chain").is_some();
if let Some(IfLet {let_pat, if_then, ..}) = IfLet::hir(cx, expr);
if !is_lint_allowed(cx, INDEX_REFUTABLE_SLICE, expr.hir_id);
if meets_msrv(self.msrv, msrvs::SLICE_PATTERNS);
if self.msrv.meets(msrvs::SLICE_PATTERNS);
let found_slices = find_slice_values(cx, let_pat);
if !found_slices.is_empty();

View file

@ -1,13 +1,11 @@
use clippy_utils::{
diagnostics::{self, span_lint_and_sugg},
meets_msrv, msrvs, source,
sugg::Sugg,
ty,
};
use clippy_utils::diagnostics::{self, span_lint_and_sugg};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{source_map::Spanned, sym};
@ -68,12 +66,12 @@ declare_clippy_lint! {
}
pub struct InstantSubtraction {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl InstantSubtraction {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -101,7 +99,7 @@ impl LateLintPass<'_> for InstantSubtraction {
} else {
if_chain! {
if !expr.span.from_expansion();
if meets_msrv(self.msrv, msrvs::TRY_FROM);
if self.msrv.meets(msrvs::TRY_FROM);
if is_an_instant(cx, lhs);
if is_a_duration(cx, rhs);

View file

@ -52,10 +52,9 @@ extern crate declare_clippy_lint;
use std::io;
use std::path::PathBuf;
use clippy_utils::parse_msrv;
use clippy_utils::msrvs::Msrv;
use rustc_data_structures::fx::FxHashSet;
use rustc_lint::{Lint, LintId};
use rustc_semver::RustcVersion;
use rustc_session::Session;
#[cfg(feature = "internal")]
@ -322,48 +321,10 @@ pub use crate::utils::conf::{lookup_conf_file, Conf};
/// Used in `./src/driver.rs`.
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, sess: &Session, conf: &Conf) {
// NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
let msrv = Msrv::read(&conf.msrv, sess);
let msrv = move || msrv.clone();
let msrv = conf.msrv.as_ref().and_then(|s| {
parse_msrv(s, None, None).or_else(|| {
sess.err(format!(
"error reading Clippy's configuration file. `{s}` is not a valid Rust version"
));
None
})
});
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv }));
}
fn read_msrv(conf: &Conf, sess: &Session) -> Option<RustcVersion> {
let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION")
.ok()
.and_then(|v| parse_msrv(&v, None, None));
let clippy_msrv = conf.msrv.as_ref().and_then(|s| {
parse_msrv(s, None, None).or_else(|| {
sess.err(format!(
"error reading Clippy's configuration file. `{s}` is not a valid Rust version"
));
None
})
});
if let Some(cargo_msrv) = cargo_msrv {
if let Some(clippy_msrv) = clippy_msrv {
// if both files have an msrv, let's compare them and emit a warning if they differ
if clippy_msrv != cargo_msrv {
sess.warn(format!(
"the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`"
));
}
Some(clippy_msrv)
} else {
Some(cargo_msrv)
}
} else {
clippy_msrv
}
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes { msrv: msrv() }));
}
#[doc(hidden)]
@ -595,43 +556,44 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(non_octal_unix_permissions::NonOctalUnixPermissions));
store.register_early_pass(|| Box::new(unnecessary_self_imports::UnnecessarySelfImports));
let msrv = read_msrv(conf, sess);
let msrv = Msrv::read(&conf.msrv, sess);
let msrv = move || msrv.clone();
let avoid_breaking_exported_api = conf.avoid_breaking_exported_api;
let allow_expect_in_tests = conf.allow_expect_in_tests;
let allow_unwrap_in_tests = conf.allow_unwrap_in_tests;
store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv)));
store.register_late_pass(move |_| Box::new(approx_const::ApproxConstant::new(msrv())));
store.register_late_pass(move |_| {
Box::new(methods::Methods::new(
avoid_breaking_exported_api,
msrv,
msrv(),
allow_expect_in_tests,
allow_unwrap_in_tests,
))
});
store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv)));
store.register_late_pass(move |_| Box::new(matches::Matches::new(msrv())));
let matches_for_let_else = conf.matches_for_let_else;
store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv, matches_for_let_else)));
store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv)));
store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv)));
store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv)));
store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv)));
store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv)));
store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv)));
store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv)));
store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv)));
store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv)));
store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv)));
store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv)));
store.register_late_pass(move |_| Box::new(manual_let_else::ManualLetElse::new(msrv(), matches_for_let_else)));
store.register_early_pass(move || Box::new(manual_non_exhaustive::ManualNonExhaustiveStruct::new(msrv())));
store.register_late_pass(move |_| Box::new(manual_non_exhaustive::ManualNonExhaustiveEnum::new(msrv())));
store.register_late_pass(move |_| Box::new(manual_strip::ManualStrip::new(msrv())));
store.register_early_pass(move || Box::new(redundant_static_lifetimes::RedundantStaticLifetimes::new(msrv())));
store.register_early_pass(move || Box::new(redundant_field_names::RedundantFieldNames::new(msrv())));
store.register_late_pass(move |_| Box::new(checked_conversions::CheckedConversions::new(msrv())));
store.register_late_pass(move |_| Box::new(mem_replace::MemReplace::new(msrv())));
store.register_late_pass(move |_| Box::new(ranges::Ranges::new(msrv())));
store.register_late_pass(move |_| Box::new(from_over_into::FromOverInto::new(msrv())));
store.register_late_pass(move |_| Box::new(use_self::UseSelf::new(msrv())));
store.register_late_pass(move |_| Box::new(missing_const_for_fn::MissingConstForFn::new(msrv())));
store.register_late_pass(move |_| Box::new(needless_question_mark::NeedlessQuestionMark));
store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv)));
store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv)));
store.register_late_pass(move |_| Box::new(casts::Casts::new(msrv())));
store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv())));
store.register_late_pass(|_| Box::new(size_of_in_element_count::SizeOfInElementCount));
store.register_late_pass(|_| Box::new(same_name_method::SameNameMethod));
let max_suggested_slice_pattern_length = conf.max_suggested_slice_pattern_length;
store.register_late_pass(move |_| {
Box::new(index_refutable_slice::IndexRefutableSlice::new(
max_suggested_slice_pattern_length,
msrv,
msrv(),
))
});
store.register_late_pass(|_| Box::<shadow::Shadow>::default());
@ -648,7 +610,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(borrow_deref_ref::BorrowDerefRef));
store.register_late_pass(|_| Box::new(no_effect::NoEffect));
store.register_late_pass(|_| Box::new(temporary_assignment::TemporaryAssignment));
store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv)));
store.register_late_pass(move |_| Box::new(transmute::Transmute::new(msrv())));
let cognitive_complexity_threshold = conf.cognitive_complexity_threshold;
store.register_late_pass(move |_| {
Box::new(cognitive_complexity::CognitiveComplexity::new(
@ -806,7 +768,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(move |_| Box::new(wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)));
store.register_late_pass(|_| Box::<redundant_pub_crate::RedundantPubCrate>::default());
store.register_late_pass(|_| Box::new(unnamed_address::UnnamedAddress));
store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv)));
store.register_late_pass(move |_| Box::new(dereference::Dereferencing::new(msrv())));
store.register_late_pass(|_| Box::new(option_if_let_else::OptionIfLetElse));
store.register_late_pass(|_| Box::new(future_not_send::FutureNotSend));
store.register_late_pass(|_| Box::new(if_let_mutex::IfLetMutex));
@ -840,7 +802,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::<vec_init_then_push::VecInitThenPush>::default());
store.register_late_pass(|_| Box::new(redundant_slicing::RedundantSlicing));
store.register_late_pass(|_| Box::new(from_str_radix_10::FromStrRadix10));
store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv)));
store.register_late_pass(move |_| Box::new(if_then_some_else_none::IfThenSomeElseNone::new(msrv())));
store.register_late_pass(|_| Box::new(bool_assert_comparison::BoolAssertComparison));
store.register_early_pass(move || Box::new(module_style::ModStyle));
store.register_late_pass(|_| Box::new(unused_async::UnusedAsync));
@ -865,14 +827,14 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
))
});
store.register_late_pass(move |_| Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks));
store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv)));
store.register_late_pass(move |_| Box::new(format_args::FormatArgs::new(msrv())));
store.register_late_pass(|_| Box::new(trailing_empty_array::TrailingEmptyArray));
store.register_early_pass(|| Box::new(octal_escapes::OctalEscapes));
store.register_late_pass(|_| Box::new(needless_late_init::NeedlessLateInit));
store.register_late_pass(|_| Box::new(return_self_not_must_use::ReturnSelfNotMustUse));
store.register_late_pass(|_| Box::new(init_numbered_fields::NumberedFields));
store.register_early_pass(|| Box::new(single_char_lifetime_names::SingleCharLifetimeNames));
store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv)));
store.register_late_pass(move |_| Box::new(manual_bits::ManualBits::new(msrv())));
store.register_late_pass(|_| Box::new(default_union_representation::DefaultUnionRepresentation));
store.register_late_pass(|_| Box::<only_used_in_recursion::OnlyUsedInRecursion>::default());
let allow_dbg_in_tests = conf.allow_dbg_in_tests;
@ -896,20 +858,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(rc_clone_in_vec_init::RcCloneInVecInit));
store.register_early_pass(|| Box::<duplicate_mod::DuplicateMod>::default());
store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv)));
store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv())));
store.register_late_pass(|_| Box::new(swap_ptr_to_ref::SwapPtrToRef));
store.register_late_pass(|_| Box::new(mismatching_type_param_order::TypeParamMismatch));
store.register_late_pass(|_| Box::new(read_zero_byte_vec::ReadZeroByteVec));
store.register_late_pass(|_| Box::new(default_instead_of_iter_empty::DefaultIterEmpty));
store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv)));
store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv)));
store.register_late_pass(move |_| Box::new(manual_rem_euclid::ManualRemEuclid::new(msrv())));
store.register_late_pass(move |_| Box::new(manual_retain::ManualRetain::new(msrv())));
let verbose_bit_mask_threshold = conf.verbose_bit_mask_threshold;
store.register_late_pass(move |_| Box::new(operators::Operators::new(verbose_bit_mask_threshold)));
store.register_late_pass(|_| Box::new(invalid_utf8_in_unchecked::InvalidUtf8InUnchecked));
store.register_late_pass(|_| Box::<std_instead_of_core::StdReexports>::default());
store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv)));
store.register_late_pass(move |_| Box::new(instant_subtraction::InstantSubtraction::new(msrv())));
store.register_late_pass(|_| Box::new(partialeq_to_none::PartialeqToNone));
store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv)));
store.register_late_pass(move |_| Box::new(manual_clamp::ManualClamp::new(msrv())));
store.register_late_pass(|_| Box::new(manual_string_new::ManualStringNew));
store.register_late_pass(|_| Box::new(unused_peekable::UnusedPeekable));
store.register_early_pass(|| Box::new(multi_assignments::MultiAssignments));
@ -920,7 +882,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(missing_trait_methods::MissingTraitMethods));
store.register_late_pass(|_| Box::new(from_raw_with_void_ptr::FromRawWithVoidPtr));
store.register_late_pass(|_| Box::new(suspicious_xor_used_as_pow::ConfusingXorAndPow));
store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv)));
store.register_late_pass(move |_| Box::new(manual_is_ascii_check::ManualIsAsciiCheck::new(msrv())));
// add lints here, do not remove this comment, it's used in `new_lint`
}

View file

@ -1,12 +1,12 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::get_parent_expr;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{get_parent_expr, meets_msrv, msrvs};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self, Ty};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::sym;
@ -34,12 +34,12 @@ declare_clippy_lint! {
#[derive(Clone)]
pub struct ManualBits {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ManualBits {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -48,7 +48,7 @@ impl_lint_pass!(ManualBits => [MANUAL_BITS]);
impl<'tcx> LateLintPass<'tcx> for ManualBits {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if !meets_msrv(self.msrv, msrvs::MANUAL_BITS) {
if !self.msrv.meets(msrvs::MANUAL_BITS) {
return;
}

View file

@ -1,28 +1,25 @@
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::higher::If;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::implements_trait;
use clippy_utils::visitors::is_const_evaluatable;
use clippy_utils::MaybePath;
use clippy_utils::{
eq_expr_value, is_diag_trait_item, is_trait_method, path_res, path_to_local_id, peel_blocks, peel_blocks_with_stmt,
};
use itertools::Itertools;
use rustc_errors::Applicability;
use rustc_errors::Diagnostic;
use rustc_hir::{
def::Res, Arm, BinOpKind, Block, Expr, ExprKind, Guard, HirId, PatKind, PathSegment, PrimTy, QPath, StmtKind,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::Ty;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{symbol::sym, Span};
use std::ops::Deref;
use clippy_utils::{
diagnostics::{span_lint_and_then, span_lint_hir_and_then},
eq_expr_value,
higher::If,
is_diag_trait_item, is_trait_method, meets_msrv, msrvs, path_res, path_to_local_id, peel_blocks,
peel_blocks_with_stmt,
sugg::Sugg,
ty::implements_trait,
visitors::is_const_evaluatable,
MaybePath,
};
use rustc_errors::Applicability;
declare_clippy_lint! {
/// ### What it does
/// Identifies good opportunities for a clamp function from std or core, and suggests using it.
@ -87,11 +84,11 @@ declare_clippy_lint! {
impl_lint_pass!(ManualClamp => [MANUAL_CLAMP]);
pub struct ManualClamp {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ManualClamp {
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -114,7 +111,7 @@ struct InputMinMax<'tcx> {
impl<'tcx> LateLintPass<'tcx> for ManualClamp {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
if !meets_msrv(self.msrv, msrvs::CLAMP) {
if !self.msrv.meets(msrvs::CLAMP) {
return;
}
if !expr.span.from_expansion() {
@ -130,7 +127,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualClamp {
}
fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) {
if !meets_msrv(self.msrv, msrvs::CLAMP) {
if !self.msrv.meets(msrvs::CLAMP) {
return;
}
for suggestion in is_two_if_pattern(cx, block) {

View file

@ -1,15 +1,12 @@
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::{diagnostics::span_lint_and_sugg, in_constant, macros::root_macro_call, source::snippet};
use rustc_ast::LitKind::{Byte, Char};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd};
use rustc_lint::{LateContext, LateLintPass};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{def_id::DefId, sym};
use clippy_utils::{
diagnostics::span_lint_and_sugg, in_constant, macros::root_macro_call, meets_msrv, msrvs, source::snippet,
};
declare_clippy_lint! {
/// ### What it does
/// Suggests to use dedicated built-in methods,
@ -45,12 +42,12 @@ declare_clippy_lint! {
impl_lint_pass!(ManualIsAsciiCheck => [MANUAL_IS_ASCII_CHECK]);
pub struct ManualIsAsciiCheck {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ManualIsAsciiCheck {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -70,11 +67,11 @@ enum CharRange {
impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if !meets_msrv(self.msrv, msrvs::IS_ASCII_DIGIT) {
if !self.msrv.meets(msrvs::IS_ASCII_DIGIT) {
return;
}
if in_constant(cx, expr.hir_id) && !meets_msrv(self.msrv, msrvs::IS_ASCII_DIGIT_CONST) {
if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::IS_ASCII_DIGIT_CONST) {
return;
}

View file

@ -1,16 +1,16 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLetOrMatch;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::peel_blocks;
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::visitors::{for_each_expr, Descend};
use clippy_utils::{meets_msrv, msrvs, peel_blocks};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::sym;
use rustc_span::Span;
@ -50,13 +50,13 @@ declare_clippy_lint! {
}
pub struct ManualLetElse {
msrv: Option<RustcVersion>,
msrv: Msrv,
matches_behaviour: MatchLintBehaviour,
}
impl ManualLetElse {
#[must_use]
pub fn new(msrv: Option<RustcVersion>, matches_behaviour: MatchLintBehaviour) -> Self {
pub fn new(msrv: Msrv, matches_behaviour: MatchLintBehaviour) -> Self {
Self {
msrv,
matches_behaviour,
@ -69,7 +69,7 @@ impl_lint_pass!(ManualLetElse => [MANUAL_LET_ELSE]);
impl<'tcx> LateLintPass<'tcx> for ManualLetElse {
fn check_stmt(&mut self, cx: &LateContext<'_>, stmt: &'tcx Stmt<'tcx>) {
let if_let_or_match = if_chain! {
if meets_msrv(self.msrv, msrvs::LET_ELSE);
if self.msrv.meets(msrvs::LET_ELSE);
if !in_external_macro(cx.sess(), stmt.span);
if let StmtKind::Local(local) = stmt.kind;
if let Some(init) = local.init;

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
use clippy_utils::is_doc_hidden;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::{is_doc_hidden, meets_msrv, msrvs};
use rustc_ast::ast::{self, VisibilityKind};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
@ -8,7 +9,6 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::{self as hir, Expr, ExprKind, QPath};
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext};
use rustc_middle::ty::DefIdTree;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::{sym, Span};
@ -63,12 +63,12 @@ declare_clippy_lint! {
#[expect(clippy::module_name_repetitions)]
pub struct ManualNonExhaustiveStruct {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ManualNonExhaustiveStruct {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -77,14 +77,14 @@ impl_lint_pass!(ManualNonExhaustiveStruct => [MANUAL_NON_EXHAUSTIVE]);
#[expect(clippy::module_name_repetitions)]
pub struct ManualNonExhaustiveEnum {
msrv: Option<RustcVersion>,
msrv: Msrv,
constructed_enum_variants: FxHashSet<(DefId, DefId)>,
potential_enums: Vec<(LocalDefId, LocalDefId, Span, Span)>,
}
impl ManualNonExhaustiveEnum {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self {
msrv,
constructed_enum_variants: FxHashSet::default(),
@ -97,7 +97,7 @@ impl_lint_pass!(ManualNonExhaustiveEnum => [MANUAL_NON_EXHAUSTIVE]);
impl EarlyLintPass for ManualNonExhaustiveStruct {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
if !meets_msrv(self.msrv, msrvs::NON_EXHAUSTIVE) {
if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) {
return;
}
@ -149,7 +149,7 @@ impl EarlyLintPass for ManualNonExhaustiveStruct {
impl<'tcx> LateLintPass<'tcx> for ManualNonExhaustiveEnum {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
if !meets_msrv(self.msrv, msrvs::NON_EXHAUSTIVE) {
if !self.msrv.meets(msrvs::NON_EXHAUSTIVE) {
return;
}

View file

@ -1,12 +1,12 @@
use clippy_utils::consts::{constant_full_int, FullInt};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{in_constant, meets_msrv, msrvs, path_to_local};
use clippy_utils::{in_constant, path_to_local};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, Node, TyKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! {
@ -34,12 +34,12 @@ declare_clippy_lint! {
}
pub struct ManualRemEuclid {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ManualRemEuclid {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -48,11 +48,11 @@ impl_lint_pass!(ManualRemEuclid => [MANUAL_REM_EUCLID]);
impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if !meets_msrv(self.msrv, msrvs::REM_EUCLID) {
if !self.msrv.meets(msrvs::REM_EUCLID) {
return;
}
if in_constant(cx, expr.hir_id) && !meets_msrv(self.msrv, msrvs::REM_EUCLID_CONST) {
if in_constant(cx, expr.hir_id) && !self.msrv.meets(msrvs::REM_EUCLID_CONST) {
return;
}

View file

@ -1,8 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{get_parent_expr, match_def_path, paths, SpanlessEq};
use clippy_utils::{meets_msrv, msrvs};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@ -50,12 +50,12 @@ declare_clippy_lint! {
}
pub struct ManualRetain {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ManualRetain {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -71,9 +71,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualRetain {
&& let hir::ExprKind::MethodCall(_, target_expr, [], _) = &collect_expr.kind
&& let Some(collect_def_id) = cx.typeck_results().type_dependent_def_id(collect_expr.hir_id)
&& match_def_path(cx, collect_def_id, &paths::CORE_ITER_COLLECT) {
check_into_iter(cx, parent_expr, left_expr, target_expr, self.msrv);
check_iter(cx, parent_expr, left_expr, target_expr, self.msrv);
check_to_owned(cx, parent_expr, left_expr, target_expr, self.msrv);
check_into_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
check_iter(cx, parent_expr, left_expr, target_expr, &self.msrv);
check_to_owned(cx, parent_expr, left_expr, target_expr, &self.msrv);
}
}
@ -85,7 +85,7 @@ fn check_into_iter(
parent_expr: &hir::Expr<'_>,
left_expr: &hir::Expr<'_>,
target_expr: &hir::Expr<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind
&& let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
@ -104,7 +104,7 @@ fn check_iter(
parent_expr: &hir::Expr<'_>,
left_expr: &hir::Expr<'_>,
target_expr: &hir::Expr<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
&& let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
@ -127,9 +127,9 @@ fn check_to_owned(
parent_expr: &hir::Expr<'_>,
left_expr: &hir::Expr<'_>,
target_expr: &hir::Expr<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if meets_msrv(msrv, msrvs::STRING_RETAIN)
if msrv.meets(msrvs::STRING_RETAIN)
&& let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
&& let Some(to_owned_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
&& match_def_path(cx, to_owned_def_id, &paths::TO_OWNED_METHOD)
@ -215,10 +215,10 @@ fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> boo
.any(|&method| match_def_path(cx, collect_def_id, method))
}
fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: Option<RustcVersion>) -> bool {
fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool {
let expr_ty = cx.typeck_results().expr_ty(expr).peel_refs();
ACCEPTABLE_TYPES.iter().any(|(ty, acceptable_msrv)| {
is_type_diagnostic_item(cx, expr_ty, *ty)
&& acceptable_msrv.map_or(true, |acceptable_msrv| meets_msrv(msrv, acceptable_msrv))
&& acceptable_msrv.map_or(true, |acceptable_msrv| msrv.meets(acceptable_msrv))
})
}

View file

@ -1,8 +1,9 @@
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{multispan_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::usage::mutated_variables;
use clippy_utils::{eq_expr_value, higher, match_def_path, meets_msrv, msrvs, paths};
use clippy_utils::{eq_expr_value, higher, match_def_path, paths};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_hir::def::Res;
@ -11,7 +12,6 @@ use rustc_hir::BinOpKind;
use rustc_hir::{BorrowKind, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Spanned;
use rustc_span::Span;
@ -48,12 +48,12 @@ declare_clippy_lint! {
}
pub struct ManualStrip {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl ManualStrip {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -68,7 +68,7 @@ enum StripKind {
impl<'tcx> LateLintPass<'tcx> for ManualStrip {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if !meets_msrv(self.msrv, msrvs::STR_STRIP_PREFIX) {
if !self.msrv.meets(msrvs::STR_STRIP_PREFIX) {
return;
}

View file

@ -23,13 +23,13 @@ mod single_match;
mod try_err;
mod wild_in_or_pats;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet_opt, walk_span_to_context};
use clippy_utils::{higher, in_constant, is_span_match, meets_msrv, msrvs};
use clippy_utils::{higher, in_constant, is_span_match};
use rustc_hir::{Arm, Expr, ExprKind, Local, MatchSource, Pat};
use rustc_lexer::{tokenize, TokenKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{Span, SpanData, SyntaxContext};
@ -930,13 +930,13 @@ declare_clippy_lint! {
#[derive(Default)]
pub struct Matches {
msrv: Option<RustcVersion>,
msrv: Msrv,
infallible_destructuring_match_linted: bool,
}
impl Matches {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self {
msrv,
..Matches::default()
@ -1000,9 +1000,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
if !from_expansion && !contains_cfg_arm(cx, expr, ex, arms) {
if source == MatchSource::Normal {
if !(meets_msrv(self.msrv, msrvs::MATCHES_MACRO)
&& match_like_matches::check_match(cx, expr, ex, arms))
{
if !(self.msrv.meets(msrvs::MATCHES_MACRO) && match_like_matches::check_match(cx, expr, ex, arms)) {
match_same_arms::check(cx, arms);
}
@ -1034,7 +1032,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches {
collapsible_match::check_if_let(cx, if_let.let_pat, if_let.if_then, if_let.if_else);
if !from_expansion {
if let Some(else_expr) = if_let.if_else {
if meets_msrv(self.msrv, msrvs::MATCHES_MACRO) {
if self.msrv.meets(msrvs::MATCHES_MACRO) {
match_like_matches::check_if_let(
cx,
expr,

View file

@ -1,14 +1,14 @@
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::ty::is_non_aggregate_primitive_type;
use clippy_utils::{is_default_equivalent, is_res_lang_ctor, meets_msrv, msrvs, path_res};
use clippy_utils::{is_default_equivalent, is_res_lang_ctor, path_res};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionNone;
use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::symbol::sym;
@ -227,12 +227,12 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
}
pub struct MemReplace {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl MemReplace {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -248,7 +248,7 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace {
then {
check_replace_option_with_none(cx, src, dest, expr.span);
check_replace_with_uninit(cx, src, dest, expr.span);
if meets_msrv(self.msrv, msrvs::MEM_TAKE) {
if self.msrv.meets(msrvs::MEM_TAKE) {
check_replace_with_default(cx, src, dest, expr.span);
}
}

View file

@ -1,25 +1,25 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_trait_method;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::{get_iterator_item_ty, is_copy};
use clippy_utils::{is_trait_method, meets_msrv, msrvs};
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_semver::RustcVersion;
use rustc_span::{sym, Span};
use super::CLONED_INSTEAD_OF_COPIED;
pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, msrv: Option<RustcVersion>) {
pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span: Span, msrv: &Msrv) {
let recv_ty = cx.typeck_results().expr_ty_adjusted(recv);
let inner_ty = match recv_ty.kind() {
// `Option<T>` -> `T`
ty::Adt(adt, subst)
if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && meets_msrv(msrv, msrvs::OPTION_COPIED) =>
if cx.tcx.is_diagnostic_item(sym::Option, adt.did()) && msrv.meets(msrvs::OPTION_COPIED) =>
{
subst.type_at(0)
},
_ if is_trait_method(cx, expr, sym::Iterator) && meets_msrv(msrv, msrvs::ITERATOR_COPIED) => {
_ if is_trait_method(cx, expr, sym::Iterator) && msrv.meets(msrvs::ITERATOR_COPIED) => {
match get_iterator_item_ty(cx, recv_ty) {
// <T as Iterator>::Item
Some(ty) => ty,

View file

@ -1,27 +1,27 @@
use super::ERR_EXPECT;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::has_debug_impl;
use clippy_utils::{meets_msrv, msrvs, ty::is_type_diagnostic_item};
use clippy_utils::ty::is_type_diagnostic_item;
use rustc_errors::Applicability;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::Ty;
use rustc_semver::RustcVersion;
use rustc_span::{sym, Span};
pub(super) fn check(
cx: &LateContext<'_>,
_expr: &rustc_hir::Expr<'_>,
recv: &rustc_hir::Expr<'_>,
msrv: Option<RustcVersion>,
expect_span: Span,
err_span: Span,
msrv: &Msrv,
) {
if_chain! {
if is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
// Test the version to make sure the lint can be showed (expect_err has been
// introduced in rust 1.17.0 : https://github.com/rust-lang/rust/pull/38982)
if meets_msrv(msrv, msrvs::EXPECT_ERR);
if msrv.meets(msrvs::EXPECT_ERR);
// Grabs the `Result<T, E>` type
let result_type = cx.typeck_results().expr_ty(recv);

View file

@ -1,10 +1,10 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::is_trait_method;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::{is_trait_method, meets_msrv, msrvs};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_semver::RustcVersion;
use rustc_span::sym;
use super::FILTER_MAP_NEXT;
@ -14,10 +14,10 @@ pub(super) fn check<'tcx>(
expr: &'tcx hir::Expr<'_>,
recv: &'tcx hir::Expr<'_>,
arg: &'tcx hir::Expr<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if is_trait_method(cx, expr, sym::Iterator) {
if !meets_msrv(msrv, msrvs::ITERATOR_FIND_MAP) {
if !msrv.meets(msrvs::ITERATOR_FIND_MAP) {
return;
}

View file

@ -1,23 +1,22 @@
//! Lint for `c.is_digit(10)`
use super::IS_DIGIT_ASCII_RADIX;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::{
consts::constant_full_int, consts::FullInt, diagnostics::span_lint_and_sugg, meets_msrv, msrvs,
source::snippet_with_applicability,
consts::constant_full_int, consts::FullInt, diagnostics::span_lint_and_sugg, source::snippet_with_applicability,
};
use rustc_errors::Applicability;
use rustc_hir::Expr;
use rustc_lint::LateContext;
use rustc_semver::RustcVersion;
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
expr: &'tcx Expr<'_>,
self_arg: &'tcx Expr<'_>,
radix: &'tcx Expr<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if !meets_msrv(msrv, msrvs::IS_ASCII_DIGIT) {
if !msrv.meets(msrvs::IS_ASCII_DIGIT) {
return;
}

View file

@ -1,7 +1,8 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::ty::{is_copy, is_type_diagnostic_item};
use clippy_utils::{is_diag_trait_item, meets_msrv, msrvs, peel_blocks};
use clippy_utils::{is_diag_trait_item, peel_blocks};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
@ -9,19 +10,12 @@ use rustc_lint::LateContext;
use rustc_middle::mir::Mutability;
use rustc_middle::ty;
use rustc_middle::ty::adjustment::Adjust;
use rustc_semver::RustcVersion;
use rustc_span::symbol::Ident;
use rustc_span::{sym, Span};
use super::MAP_CLONE;
pub(super) fn check(
cx: &LateContext<'_>,
e: &hir::Expr<'_>,
recv: &hir::Expr<'_>,
arg: &hir::Expr<'_>,
msrv: Option<RustcVersion>,
) {
pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>, msrv: &Msrv) {
if_chain! {
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(e.hir_id);
if cx.tcx.impl_of_method(method_id)
@ -97,10 +91,10 @@ fn lint_needless_cloning(cx: &LateContext<'_>, root: Span, receiver: Span) {
);
}
fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool, msrv: Option<RustcVersion>) {
fn lint_explicit_closure(cx: &LateContext<'_>, replace: Span, root: Span, is_copy: bool, msrv: &Msrv) {
let mut applicability = Applicability::MachineApplicable;
let (message, sugg_method) = if is_copy && meets_msrv(msrv, msrvs::ITERATOR_COPIED) {
let (message, sugg_method) = if is_copy && msrv.meets(msrvs::ITERATOR_COPIED) {
("you are using an explicit closure for copying elements", "copied")
} else {
("you are using an explicit closure for cloning elements", "cloned")

View file

@ -1,12 +1,11 @@
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::mutated_variables;
use clippy_utils::{meets_msrv, msrvs};
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_semver::RustcVersion;
use rustc_span::symbol::sym;
use super::MAP_UNWRAP_OR;
@ -19,13 +18,13 @@ pub(super) fn check<'tcx>(
recv: &'tcx hir::Expr<'_>,
map_arg: &'tcx hir::Expr<'_>,
unwrap_arg: &'tcx hir::Expr<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) -> bool {
// lint if the caller of `map()` is an `Option`
let is_option = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Option);
let is_result = is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(recv), sym::Result);
if is_result && !meets_msrv(msrv, msrvs::RESULT_MAP_OR_ELSE) {
if is_result && !msrv.meets(msrvs::RESULT_MAP_OR_ELSE) {
return false;
}

View file

@ -104,8 +104,9 @@ mod zst_offset;
use bind_instead_of_map::BindInsteadOfMap;
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::{contains_ty_adt_constructor_opaque, implements_trait, is_copy, is_type_diagnostic_item};
use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, meets_msrv, msrvs, return_ty};
use clippy_utils::{contains_return, is_bool, is_trait_method, iter_input_pats, return_ty};
use if_chain::if_chain;
use rustc_hir as hir;
use rustc_hir::{Expr, ExprKind, TraitItem, TraitItemKind};
@ -113,7 +114,6 @@ use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::{self, TraitRef, Ty};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::{sym, Span};
@ -3163,7 +3163,7 @@ declare_clippy_lint! {
pub struct Methods {
avoid_breaking_exported_api: bool,
msrv: Option<RustcVersion>,
msrv: Msrv,
allow_expect_in_tests: bool,
allow_unwrap_in_tests: bool,
}
@ -3172,7 +3172,7 @@ impl Methods {
#[must_use]
pub fn new(
avoid_breaking_exported_api: bool,
msrv: Option<RustcVersion>,
msrv: Msrv,
allow_expect_in_tests: bool,
allow_unwrap_in_tests: bool,
) -> Self {
@ -3325,7 +3325,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
single_char_add_str::check(cx, expr, receiver, args);
into_iter_on_ref::check(cx, expr, method_span, method_call.ident.name, receiver);
single_char_pattern::check(cx, expr, method_call.ident.name, receiver, args);
unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, self.msrv);
unnecessary_to_owned::check(cx, expr, method_call.ident.name, receiver, args, &self.msrv);
},
hir::ExprKind::Binary(op, lhs, rhs) if op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne => {
let mut info = BinaryExprInfo {
@ -3501,7 +3501,7 @@ impl Methods {
("as_mut", []) => useless_asref::check(cx, expr, "as_mut", recv),
("as_ref", []) => useless_asref::check(cx, expr, "as_ref", recv),
("assume_init", []) => uninit_assumed_init::check(cx, expr, recv),
("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, self.msrv),
("cloned", []) => cloned_instead_of_copied::check(cx, expr, recv, span, &self.msrv),
("collect", []) if is_trait_method(cx, expr, sym::Iterator) => {
needless_collect::check(cx, span, expr, recv, call_span);
match method_call(recv) {
@ -3512,7 +3512,7 @@ impl Methods {
map_collect_result_unit::check(cx, expr, m_recv, m_arg);
},
Some(("take", take_self_arg, [take_arg], _, _)) => {
if meets_msrv(self.msrv, msrvs::STR_REPEAT) {
if self.msrv.meets(msrvs::STR_REPEAT) {
manual_str_repeat::check(cx, expr, recv, take_self_arg, take_arg);
}
},
@ -3539,7 +3539,7 @@ impl Methods {
},
("expect", [_]) => match method_call(recv) {
Some(("ok", recv, [], _, _)) => ok_expect::check(cx, expr, recv),
Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, self.msrv, span, err_span),
Some(("err", recv, [], err_span, _)) => err_expect::check(cx, expr, recv, span, err_span, &self.msrv),
_ => expect_used::check(cx, expr, recv, false, self.allow_expect_in_tests),
},
("expect_err", [_]) => expect_used::check(cx, expr, recv, true, self.allow_expect_in_tests),
@ -3578,7 +3578,7 @@ impl Methods {
unit_hash::check(cx, expr, recv, arg);
},
("is_file", []) => filetype_is_file::check(cx, expr, recv),
("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, self.msrv),
("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, &self.msrv),
("is_none", []) => check_is_some_is_none(cx, expr, recv, false),
("is_some", []) => check_is_some_is_none(cx, expr, recv, true),
("iter" | "iter_mut" | "into_iter", []) => {
@ -3601,7 +3601,7 @@ impl Methods {
},
(name @ ("map" | "map_err"), [m_arg]) => {
if name == "map" {
map_clone::check(cx, expr, recv, m_arg, self.msrv);
map_clone::check(cx, expr, recv, m_arg, &self.msrv);
if let Some((map_name @ ("iter" | "into_iter"), recv2, _, _, _)) = method_call(recv) {
iter_kv_map::check(cx, map_name, expr, recv2, m_arg);
}
@ -3610,8 +3610,8 @@ impl Methods {
}
if let Some((name, recv2, args, span2,_)) = method_call(recv) {
match (name, args) {
("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, self.msrv),
("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, self.msrv),
("as_mut", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, true, &self.msrv),
("as_ref", []) => option_as_ref_deref::check(cx, expr, recv2, m_arg, false, &self.msrv),
("filter", [f_arg]) => {
filter_map::check(cx, expr, recv2, f_arg, span2, recv, m_arg, span, false);
},
@ -3632,7 +3632,7 @@ impl Methods {
match (name2, args2) {
("cloned", []) => iter_overeager_cloned::check(cx, expr, recv, recv2, false, false),
("filter", [arg]) => filter_next::check(cx, expr, recv2, arg),
("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, self.msrv),
("filter_map", [arg]) => filter_map_next::check(cx, expr, recv2, arg, &self.msrv),
("iter", []) => iter_next_slice::check(cx, expr, recv2),
("skip", [arg]) => iter_skip_next::check(cx, expr, recv2, arg),
("skip_while", [_]) => skip_while_next::check(cx, expr),
@ -3680,10 +3680,10 @@ impl Methods {
vec_resize_to_zero::check(cx, expr, count_arg, default_arg, span);
},
("seek", [arg]) => {
if meets_msrv(self.msrv, msrvs::SEEK_FROM_CURRENT) {
if self.msrv.meets(msrvs::SEEK_FROM_CURRENT) {
seek_from_current::check(cx, expr, recv, arg);
}
if meets_msrv(self.msrv, msrvs::SEEK_REWIND) {
if self.msrv.meets(msrvs::SEEK_REWIND) {
seek_to_start_instead_of_rewind::check(cx, expr, recv, arg, span);
}
},
@ -3699,7 +3699,7 @@ impl Methods {
("splitn" | "rsplitn", [count_arg, pat_arg]) => {
if let Some((Constant::Int(count), _)) = constant(cx, cx.typeck_results(), count_arg) {
suspicious_splitn::check(cx, name, expr, recv, count);
str_splitn::check(cx, name, expr, recv, pat_arg, count, self.msrv);
str_splitn::check(cx, name, expr, recv, pat_arg, count, &self.msrv);
}
},
("splitn_mut" | "rsplitn_mut", [count_arg, _]) => {
@ -3717,7 +3717,7 @@ impl Methods {
},
("take", []) => needless_option_take::check(cx, expr, recv),
("then", [arg]) => {
if !meets_msrv(self.msrv, msrvs::BOOL_THEN_SOME) {
if !self.msrv.meets(msrvs::BOOL_THEN_SOME) {
return;
}
unnecessary_lazy_eval::check(cx, expr, recv, arg, "then_some");
@ -3760,7 +3760,7 @@ impl Methods {
},
("unwrap_or_else", [u_arg]) => match method_call(recv) {
Some(("map", recv, [map_arg], _, _))
if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, self.msrv) => {},
if map_unwrap_or::check(cx, expr, recv, map_arg, u_arg, &self.msrv) => {},
_ => {
unwrap_or_else_default::check(cx, expr, recv, u_arg);
unnecessary_lazy_eval::check(cx, expr, recv, u_arg, "unwrap_or");

View file

@ -1,13 +1,13 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{match_def_path, meets_msrv, msrvs, path_to_local_id, paths, peel_blocks};
use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir as hir;
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_semver::RustcVersion;
use rustc_span::sym;
use super::OPTION_AS_REF_DEREF;
@ -19,9 +19,9 @@ pub(super) fn check(
as_ref_recv: &hir::Expr<'_>,
map_arg: &hir::Expr<'_>,
is_mut: bool,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if !meets_msrv(msrv, msrvs::OPTION_AS_DEREF) {
if !msrv.meets(msrvs::OPTION_AS_DEREF) {
return;
}

View file

@ -1,9 +1,10 @@
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_context;
use clippy_utils::usage::local_used_after_expr;
use clippy_utils::visitors::{for_each_expr_with_closures, Descend};
use clippy_utils::{is_diag_item_method, match_def_path, meets_msrv, msrvs, path_to_local_id, paths};
use clippy_utils::{is_diag_item_method, match_def_path, path_to_local_id, paths};
use core::ops::ControlFlow;
use if_chain::if_chain;
use rustc_errors::Applicability;
@ -12,7 +13,6 @@ use rustc_hir::{
};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_semver::RustcVersion;
use rustc_span::{sym, Span, Symbol, SyntaxContext};
use super::{MANUAL_SPLIT_ONCE, NEEDLESS_SPLITN};
@ -24,7 +24,7 @@ pub(super) fn check(
self_arg: &Expr<'_>,
pat_arg: &Expr<'_>,
count: u128,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if count < 2 || !cx.typeck_results().expr_ty_adjusted(self_arg).peel_refs().is_str() {
return;
@ -34,7 +34,7 @@ pub(super) fn check(
IterUsageKind::Nth(n) => count > n + 1,
IterUsageKind::NextTuple => count > 2,
};
let manual = count == 2 && meets_msrv(msrv, msrvs::STR_SPLIT_ONCE);
let manual = count == 2 && msrv.meets(msrvs::STR_SPLIT_ONCE);
match parse_iter_usage(cx, expr.span.ctxt(), cx.tcx.hir().parent_iter(expr.hir_id)) {
Some(usage) if needless(usage.kind) => lint_needless(cx, method_name, expr, self_arg, pat_arg),

View file

@ -1,11 +1,11 @@
use super::implicit_clone::is_clone_like;
use super::unnecessary_iter_cloned::{self, is_into_iter};
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_opt;
use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait, is_copy, peel_mid_ty_refs};
use clippy_utils::visitors::find_all_ret_expressions;
use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
use clippy_utils::{meets_msrv, msrvs};
use rustc_errors::Applicability;
use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
use rustc_hir_analysis::check::{FnCtxt, Inherited};
@ -16,7 +16,6 @@ use rustc_middle::ty::adjustment::{Adjust, Adjustment, OverloadedDeref};
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, SubstsRef};
use rustc_middle::ty::EarlyBinder;
use rustc_middle::ty::{self, ParamTy, PredicateKind, ProjectionPredicate, TraitPredicate, Ty};
use rustc_semver::RustcVersion;
use rustc_span::{sym, Symbol};
use rustc_trait_selection::traits::{query::evaluate_obligation::InferCtxtExt as _, Obligation, ObligationCause};
use std::cmp::max;
@ -29,7 +28,7 @@ pub fn check<'tcx>(
method_name: Symbol,
receiver: &'tcx Expr<'_>,
args: &'tcx [Expr<'_>],
msrv: Option<RustcVersion>,
msrv: &Msrv,
) {
if_chain! {
if let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
@ -200,7 +199,7 @@ fn check_into_iter_call_arg(
expr: &Expr<'_>,
method_name: Symbol,
receiver: &Expr<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) -> bool {
if_chain! {
if let Some(parent) = get_parent_expr(cx, expr);
@ -215,7 +214,7 @@ fn check_into_iter_call_arg(
if unnecessary_iter_cloned::check_for_loop_iter(cx, parent, method_name, receiver, true) {
return true;
}
let cloned_or_copied = if is_copy(cx, item_ty) && meets_msrv(msrv, msrvs::ITERATOR_COPIED) {
let cloned_or_copied = if is_copy(cx, item_ty) && msrv.meets(msrvs::ITERATOR_COPIED) {
"copied"
} else {
"cloned"

View file

@ -1,9 +1,8 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::qualify_min_const_fn::is_min_const_fn;
use clippy_utils::ty::has_drop;
use clippy_utils::{
fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, meets_msrv, msrvs, trait_ref_of_method,
};
use clippy_utils::{fn_has_unsatisfiable_preds, is_entrypoint_fn, is_from_proc_macro, trait_ref_of_method};
use rustc_hir as hir;
use rustc_hir::def_id::CRATE_DEF_ID;
use rustc_hir::intravisit::FnKind;
@ -11,7 +10,6 @@ use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
@ -75,12 +73,12 @@ declare_clippy_lint! {
impl_lint_pass!(MissingConstForFn => [MISSING_CONST_FOR_FN]);
pub struct MissingConstForFn {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl MissingConstForFn {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -95,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
span: Span,
hir_id: HirId,
) {
if !meets_msrv(self.msrv, msrvs::CONST_IF_MATCH) {
if !self.msrv.meets(msrvs::CONST_IF_MATCH) {
return;
}
@ -152,7 +150,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingConstForFn {
let mir = cx.tcx.optimized_mir(def_id);
if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, self.msrv) {
if let Err((span, err)) = is_min_const_fn(cx.tcx, mir, &self.msrv) {
if cx.tcx.is_const_fn_raw(def_id.to_def_id()) {
cx.tcx.sess.span_err(span, err.as_ref());
}

View file

@ -1,16 +1,16 @@
use clippy_utils::consts::{constant, Constant};
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::higher;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{snippet, snippet_opt, snippet_with_applicability};
use clippy_utils::sugg::Sugg;
use clippy_utils::{get_parent_expr, in_constant, is_integer_const, meets_msrv, msrvs, path_to_local};
use clippy_utils::{get_parent_expr, in_constant, is_integer_const, path_to_local};
use if_chain::if_chain;
use rustc_ast::ast::RangeLimits;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, HirId};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::{Span, Spanned};
use std::cmp::Ordering;
@ -161,12 +161,12 @@ declare_clippy_lint! {
}
pub struct Ranges {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl Ranges {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -181,7 +181,7 @@ impl_lint_pass!(Ranges => [
impl<'tcx> LateLintPass<'tcx> for Ranges {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::Binary(ref op, l, r) = expr.kind {
if meets_msrv(self.msrv, msrvs::RANGE_CONTAINS) {
if self.msrv.meets(msrvs::RANGE_CONTAINS) {
check_possible_range_contains(cx, op.node, l, r, expr, expr.span);
}
}

View file

@ -1,10 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::{meets_msrv, msrvs};
use clippy_utils::msrvs::{self, Msrv};
use rustc_ast::ast::{Expr, ExprKind};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! {
@ -37,12 +36,12 @@ declare_clippy_lint! {
}
pub struct RedundantFieldNames {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl RedundantFieldNames {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -51,7 +50,7 @@ impl_lint_pass!(RedundantFieldNames => [REDUNDANT_FIELD_NAMES]);
impl EarlyLintPass for RedundantFieldNames {
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
if !meets_msrv(self.msrv, msrvs::FIELD_INIT_SHORTHAND) {
if !self.msrv.meets(msrvs::FIELD_INIT_SHORTHAND) {
return;
}

View file

@ -1,10 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet;
use clippy_utils::{meets_msrv, msrvs};
use rustc_ast::ast::{Item, ItemKind, Ty, TyKind};
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
declare_clippy_lint! {
@ -34,12 +33,12 @@ declare_clippy_lint! {
}
pub struct RedundantStaticLifetimes {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl RedundantStaticLifetimes {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -96,7 +95,7 @@ impl RedundantStaticLifetimes {
impl EarlyLintPass for RedundantStaticLifetimes {
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
if !meets_msrv(self.msrv, msrvs::STATIC_IN_CONST) {
if !self.msrv.meets(msrvs::STATIC_IN_CONST) {
return;
}

View file

@ -16,10 +16,10 @@ mod utils;
mod wrong_transmute;
use clippy_utils::in_constant;
use clippy_utils::msrvs::Msrv;
use if_chain::if_chain;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::symbol::sym;
@ -410,7 +410,7 @@ declare_clippy_lint! {
}
pub struct Transmute {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl_lint_pass!(Transmute => [
CROSSPOINTER_TRANSMUTE,
@ -431,7 +431,7 @@ impl_lint_pass!(Transmute => [
]);
impl Transmute {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -461,7 +461,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
let linted = wrong_transmute::check(cx, e, from_ty, to_ty)
| crosspointer_transmute::check(cx, e, from_ty, to_ty)
| transmuting_null::check(cx, e, arg, to_ty)
| transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, self.msrv)
| transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv)
| transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context)
| transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
| transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)

View file

@ -1,12 +1,12 @@
use super::TRANSMUTE_PTR_TO_REF;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{meets_msrv, msrvs, sugg};
use clippy_utils::sugg;
use rustc_errors::Applicability;
use rustc_hir::{self as hir, Expr, GenericArg, Mutability, Path, TyKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, Ty, TypeVisitable};
use rustc_semver::RustcVersion;
/// Checks for `transmute_ptr_to_ref` lint.
/// Returns `true` if it's triggered, otherwise returns `false`.
@ -17,7 +17,7 @@ pub(super) fn check<'tcx>(
to_ty: Ty<'tcx>,
arg: &'tcx Expr<'_>,
path: &'tcx Path<'_>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) -> bool {
match (&from_ty.kind(), &to_ty.kind()) {
(ty::RawPtr(from_ptr_ty), ty::Ref(_, to_ref_ty, mutbl)) => {
@ -37,7 +37,7 @@ pub(super) fn check<'tcx>(
let sugg = if let Some(ty) = get_explicit_type(path) {
let ty_snip = snippet_with_applicability(cx, ty.span, "..", &mut app);
if meets_msrv(msrv, msrvs::POINTER_CAST) {
if msrv.meets(msrvs::POINTER_CAST) {
format!("{deref}{}.cast::<{ty_snip}>()", arg.maybe_par())
} else if from_ptr_ty.has_erased_regions() {
sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {ty_snip}"))).to_string()
@ -46,7 +46,7 @@ pub(super) fn check<'tcx>(
}
} else if from_ptr_ty.ty == *to_ref_ty {
if from_ptr_ty.has_erased_regions() {
if meets_msrv(msrv, msrvs::POINTER_CAST) {
if msrv.meets(msrvs::POINTER_CAST) {
format!("{deref}{}.cast::<{to_ref_ty}>()", arg.maybe_par())
} else {
sugg::make_unop(deref, arg.as_ty(format!("{cast} () as {cast} {to_ref_ty}")))

View file

@ -2,14 +2,14 @@
use clippy_utils::ast_utils::{eq_field_pat, eq_id, eq_maybe_qself, eq_pat, eq_path};
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::{meets_msrv, msrvs, over};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::over;
use rustc_ast::mut_visit::*;
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, Mutability, Pat, PatKind, PatKind::*, DUMMY_NODE_ID};
use rustc_ast_pretty::pprust;
use rustc_errors::Applicability;
use rustc_lint::{EarlyContext, EarlyLintPass};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::DUMMY_SP;
@ -45,14 +45,13 @@ declare_clippy_lint! {
"unnested or-patterns, e.g., `Foo(Bar) | Foo(Baz) instead of `Foo(Bar | Baz)`"
}
#[derive(Clone, Copy)]
pub struct UnnestedOrPatterns {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl UnnestedOrPatterns {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self { msrv }
}
}
@ -61,13 +60,13 @@ impl_lint_pass!(UnnestedOrPatterns => [UNNESTED_OR_PATTERNS]);
impl EarlyLintPass for UnnestedOrPatterns {
fn check_arm(&mut self, cx: &EarlyContext<'_>, a: &ast::Arm) {
if meets_msrv(self.msrv, msrvs::OR_PATTERNS) {
if self.msrv.meets(msrvs::OR_PATTERNS) {
lint_unnested_or_patterns(cx, &a.pat);
}
}
fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
if meets_msrv(self.msrv, msrvs::OR_PATTERNS) {
if self.msrv.meets(msrvs::OR_PATTERNS) {
if let ast::ExprKind::Let(pat, _, _) = &e.kind {
lint_unnested_or_patterns(cx, pat);
}
@ -75,13 +74,13 @@ impl EarlyLintPass for UnnestedOrPatterns {
}
fn check_param(&mut self, cx: &EarlyContext<'_>, p: &ast::Param) {
if meets_msrv(self.msrv, msrvs::OR_PATTERNS) {
if self.msrv.meets(msrvs::OR_PATTERNS) {
lint_unnested_or_patterns(cx, &p.pat);
}
}
fn check_local(&mut self, cx: &EarlyContext<'_>, l: &ast::Local) {
if meets_msrv(self.msrv, msrvs::OR_PATTERNS) {
if self.msrv.meets(msrvs::OR_PATTERNS) {
lint_unnested_or_patterns(cx, &l.pat);
}
}

View file

@ -1,6 +1,7 @@
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::is_from_proc_macro;
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::ty::same_type_and_consts;
use clippy_utils::{is_from_proc_macro, meets_msrv, msrvs};
use if_chain::if_chain;
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::Applicability;
@ -14,7 +15,6 @@ use rustc_hir::{
};
use rustc_hir_analysis::hir_ty_to_ty;
use rustc_lint::{LateContext, LateLintPass};
use rustc_semver::RustcVersion;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
@ -57,13 +57,13 @@ declare_clippy_lint! {
#[derive(Default)]
pub struct UseSelf {
msrv: Option<RustcVersion>,
msrv: Msrv,
stack: Vec<StackItem>,
}
impl UseSelf {
#[must_use]
pub fn new(msrv: Option<RustcVersion>) -> Self {
pub fn new(msrv: Msrv) -> Self {
Self {
msrv,
..Self::default()
@ -199,7 +199,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) {
if_chain! {
if !hir_ty.span.from_expansion();
if meets_msrv(self.msrv, msrvs::TYPE_ALIAS_ENUM_VARIANTS);
if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS);
if let Some(&StackItem::Check {
impl_id,
in_body,
@ -228,7 +228,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if_chain! {
if !expr.span.from_expansion();
if meets_msrv(self.msrv, msrvs::TYPE_ALIAS_ENUM_VARIANTS);
if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS);
if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
if cx.typeck_results().expr_ty(expr) == cx.tcx.type_of(impl_id);
then {} else { return; }
@ -248,7 +248,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) {
if_chain! {
if !pat.span.from_expansion();
if meets_msrv(self.msrv, msrvs::TYPE_ALIAS_ENUM_VARIANTS);
if self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS);
if let Some(&StackItem::Check { impl_id, .. }) = self.stack.last();
// get the path from the pattern
if let PatKind::Path(QPath::Resolved(_, path))

View file

@ -41,7 +41,7 @@ impl LateLintPass<'_> for MsrvAttrImpl {
.type_of(f.did)
.walk()
.filter(|t| matches!(t.unpack(), GenericArgKind::Type(_)))
.any(|t| match_type(cx, t.expect_ty(), &paths::RUSTC_VERSION))
.any(|t| match_type(cx, t.expect_ty(), &paths::MSRV))
});
if !items.iter().any(|item| item.ident.name == sym!(enter_lint_attrs));
then {

View file

@ -105,8 +105,6 @@ use rustc_middle::ty::{
layout::IntegerExt, BorrowKind, ClosureKind, DefIdTree, Ty, TyCtxt, TypeAndMut, TypeVisitable, UpvarCapture,
};
use rustc_middle::ty::{FloatTy, IntTy, UintTy};
use rustc_semver::RustcVersion;
use rustc_session::Session;
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::source_map::SourceMap;
use rustc_span::sym;
@ -118,36 +116,17 @@ use crate::consts::{constant, Constant};
use crate::ty::{can_partially_move_ty, expr_sig, is_copy, is_recursively_primitive_type, ty_is_fn_once_param};
use crate::visitors::for_each_expr;
pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
if let Ok(version) = RustcVersion::parse(msrv) {
return Some(version);
} else if let Some(sess) = sess {
if let Some(span) = span {
sess.span_err(span, format!("`{msrv}` is not a valid Rust version"));
}
}
None
}
pub fn meets_msrv(msrv: Option<RustcVersion>, lint_msrv: RustcVersion) -> bool {
msrv.map_or(true, |msrv| msrv.meets(lint_msrv))
}
#[macro_export]
macro_rules! extract_msrv_attr {
($context:ident) => {
fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
let sess = rustc_lint::LintContext::sess(cx);
match $crate::get_unique_inner_attr(sess, attrs, "msrv") {
Some(msrv_attr) => {
if let Some(msrv) = msrv_attr.value_str() {
self.msrv = $crate::parse_msrv(&msrv.to_string(), Some(sess), Some(msrv_attr.span));
} else {
sess.span_err(msrv_attr.span, "bad clippy attribute");
}
},
_ => (),
}
self.msrv.enter_lint_attrs(sess, attrs);
}
fn exit_lint_attrs(&mut self, cx: &rustc_lint::$context<'_>, attrs: &[rustc_ast::ast::Attribute]) {
let sess = rustc_lint::LintContext::sess(cx);
self.msrv.exit_lint_attrs(sess, attrs);
}
};
}

View file

@ -1,4 +1,11 @@
use std::sync::OnceLock;
use rustc_ast::Attribute;
use rustc_semver::RustcVersion;
use rustc_session::Session;
use rustc_span::Span;
use crate::attrs::get_unique_inner_attr;
macro_rules! msrv_aliases {
($($major:literal,$minor:literal,$patch:literal {
@ -40,3 +47,97 @@ msrv_aliases! {
1,16,0 { STR_REPEAT }
1,55,0 { SEEK_REWIND }
}
fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
if let Ok(version) = RustcVersion::parse(msrv) {
return Some(version);
} else if let Some(sess) = sess {
if let Some(span) = span {
sess.span_err(span, format!("`{msrv}` is not a valid Rust version"));
}
}
None
}
/// Tracks the current MSRV from `clippy.toml`, `Cargo.toml` or set via `#[clippy::msrv]`
#[derive(Debug, Clone, Default)]
pub struct Msrv {
stack: Vec<RustcVersion>,
}
impl Msrv {
fn new(initial: Option<RustcVersion>) -> Self {
Self {
stack: Vec::from_iter(initial),
}
}
fn read_inner(conf_msrv: &Option<String>, sess: &Session) -> Self {
let cargo_msrv = std::env::var("CARGO_PKG_RUST_VERSION")
.ok()
.and_then(|v| parse_msrv(&v, None, None));
let clippy_msrv = conf_msrv.as_ref().and_then(|s| {
parse_msrv(s, None, None).or_else(|| {
sess.err(format!(
"error reading Clippy's configuration file. `{s}` is not a valid Rust version"
));
None
})
});
// if both files have an msrv, let's compare them and emit a warning if they differ
if let Some(cargo_msrv) = cargo_msrv
&& let Some(clippy_msrv) = clippy_msrv
&& clippy_msrv != cargo_msrv
{
sess.warn(format!(
"the MSRV in `clippy.toml` and `Cargo.toml` differ; using `{clippy_msrv}` from `clippy.toml`"
));
}
Self::new(clippy_msrv.or(cargo_msrv))
}
/// Set the initial MSRV from the Clippy config file or from Cargo due to the `rust-version`
/// field in `Cargo.toml`
///
/// Returns a `&'static Msrv` as `Copy` types are more easily passed to the
/// `register_{late,early}_pass` callbacks
pub fn read(conf_msrv: &Option<String>, sess: &Session) -> &'static Self {
static PARSED: OnceLock<Msrv> = OnceLock::new();
PARSED.get_or_init(|| Self::read_inner(conf_msrv, sess))
}
pub fn current(&self) -> Option<RustcVersion> {
self.stack.last().copied()
}
pub fn meets(&self, required: RustcVersion) -> bool {
self.current().map_or(true, |version| version.meets(required))
}
fn parse_attr(sess: &Session, attrs: &[Attribute]) -> Option<RustcVersion> {
if let Some(msrv_attr) = get_unique_inner_attr(sess, attrs, "msrv") {
if let Some(msrv) = msrv_attr.value_str() {
return parse_msrv(&msrv.to_string(), Some(sess), Some(msrv_attr.span));
}
sess.span_err(msrv_attr.span, "bad clippy attribute");
}
None
}
pub fn enter_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) {
if let Some(version) = Self::parse_attr(sess, attrs) {
self.stack.push(version);
}
}
pub fn exit_lint_attrs(&mut self, sess: &Session, attrs: &[Attribute]) {
if Self::parse_attr(sess, attrs).is_some() {
self.stack.pop();
}
}
}

View file

@ -60,6 +60,8 @@ pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
#[cfg(feature = "internal")]
pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
pub const MEM_SWAP: [&str; 3] = ["core", "mem", "swap"];
#[cfg(feature = "internal")]
pub const MSRV: [&str; 3] = ["clippy_utils", "msrvs", "Msrv"];
pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
@ -101,8 +103,6 @@ pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "re_bytes", "Regex", "new"];
pub const REGEX_BYTES_SET_NEW: [&str; 5] = ["regex", "re_set", "bytes", "RegexSet", "new"];
pub const REGEX_NEW: [&str; 4] = ["regex", "re_unicode", "Regex", "new"];
pub const REGEX_SET_NEW: [&str; 5] = ["regex", "re_set", "unicode", "RegexSet", "new"];
#[cfg(feature = "internal")]
pub const RUSTC_VERSION: [&str; 2] = ["rustc_semver", "RustcVersion"];
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];

View file

@ -3,6 +3,7 @@
// of terminologies might not be relevant in the context of Clippy. Note that its behavior might
// differ from the time of `rustc` even if the name stays the same.
use crate::msrvs::Msrv;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
@ -18,7 +19,7 @@ use std::borrow::Cow;
type McfResult = Result<(), (Span, Cow<'static, str>)>;
pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: Option<RustcVersion>) -> McfResult {
pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) -> McfResult {
let def_id = body.source.def_id();
let mut current = def_id;
loop {
@ -280,7 +281,7 @@ fn check_terminator<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
terminator: &Terminator<'tcx>,
msrv: Option<RustcVersion>,
msrv: &Msrv,
) -> McfResult {
let span = terminator.source_info.span;
match &terminator.kind {
@ -364,7 +365,7 @@ fn check_terminator<'tcx>(
}
}
fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<RustcVersion>) -> bool {
fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
tcx.is_const_fn(def_id)
&& tcx.lookup_const_stability(def_id).map_or(true, |const_stab| {
if let rustc_attr::StabilityLevel::Stable { since, .. } = const_stab.level {
@ -383,15 +384,12 @@ fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: Option<RustcVersion>) -> bo
let since = rustc_span::Symbol::intern(short_version);
crate::meets_msrv(
msrv,
RustcVersion::parse(since.as_str()).unwrap_or_else(|err| {
panic!("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted: `{since}`, {err:?}")
}),
)
msrv.meets(RustcVersion::parse(since.as_str()).unwrap_or_else(|err| {
panic!("`rustc_attr::StabilityLevel::Stable::since` is ill-formatted: `{since}`, {err:?}")
}))
} else {
// Unstable const fn with the feature enabled.
msrv.is_none()
msrv.current().is_none()
}
})
}

View file

@ -11,9 +11,9 @@ extern crate rustc_middle;
#[macro_use]
extern crate rustc_session;
use clippy_utils::extract_msrv_attr;
use clippy_utils::msrvs::Msrv;
use rustc_hir::Expr;
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
use rustc_semver::RustcVersion;
declare_lint! {
pub TEST_LINT,
@ -22,7 +22,7 @@ declare_lint! {
}
struct Pass {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl_lint_pass!(Pass => [TEST_LINT]);

View file

@ -11,9 +11,9 @@ extern crate rustc_middle;
#[macro_use]
extern crate rustc_session;
use clippy_utils::extract_msrv_attr;
use clippy_utils::msrvs::Msrv;
use rustc_hir::Expr;
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
use rustc_semver::RustcVersion;
declare_lint! {
pub TEST_LINT,
@ -22,7 +22,7 @@ declare_lint! {
}
struct Pass {
msrv: Option<RustcVersion>,
msrv: Msrv,
}
impl_lint_pass!(Pass => [TEST_LINT]);

View file

@ -27,3 +27,26 @@ fn no_patch_meets() {
#![clippy::msrv = "1.43"]
let log2_10 = 3.321928094887362;
}
// https://github.com/rust-lang/rust-clippy/issues/6920
fn scoping() {
mod m {
#![clippy::msrv = "1.42.0"]
}
// Should warn
let log2_10 = 3.321928094887362;
mod a {
#![clippy::msrv = "1.42.0"]
fn should_warn() {
#![clippy::msrv = "1.43.0"]
let log2_10 = 3.321928094887362;
}
fn should_not_warn() {
let log2_10 = 3.321928094887362;
}
}
}

View file

@ -23,5 +23,21 @@ LL | let log2_10 = 3.321928094887362;
|
= help: consider using the constant directly
error: aborting due to 3 previous errors
error: approximate value of `f{32, 64}::consts::LOG2_10` found
--> $DIR/min_rust_version_attr.rs:38:19
|
LL | let log2_10 = 3.321928094887362;
| ^^^^^^^^^^^^^^^^^
|
= help: consider using the constant directly
error: approximate value of `f{32, 64}::consts::LOG2_10` found
--> $DIR/min_rust_version_attr.rs:45:27
|
LL | let log2_10 = 3.321928094887362;
| ^^^^^^^^^^^^^^^^^
|
= help: consider using the constant directly
error: aborting due to 5 previous errors