diff --git a/clippy_lints/src/from_over_into.rs b/clippy_lints/src/from_over_into.rs index fe7120b0f9a..c7988d6f01f 100644 --- a/clippy_lints/src/from_over_into.rs +++ b/clippy_lints/src/from_over_into.rs @@ -1,9 +1,12 @@ use crate::utils::paths::INTO; -use crate::utils::{match_def_path, span_lint_and_help}; +use crate::utils::{match_def_path, meets_msrv, span_lint_and_help}; use if_chain::if_chain; use rustc_hir as hir; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_semver::RustcVersion; +use rustc_session::{declare_tool_lint, impl_lint_pass}; + +const FROM_OVER_INTO_MSRV: RustcVersion = RustcVersion::new(1, 41, 0); declare_clippy_lint! { /// **What it does:** Searches for implementations of the `Into<..>` trait and suggests to implement `From<..>` instead. @@ -38,10 +41,25 @@ "Warns on implementations of `Into<..>` to use `From<..>`" } -declare_lint_pass!(FromOverInto => [FROM_OVER_INTO]); +pub struct FromOverInto { + msrv: Option, +} + +impl FromOverInto { + #[must_use] + pub fn new(msrv: Option) -> Self { + FromOverInto { msrv } + } +} + +impl_lint_pass!(FromOverInto => [FROM_OVER_INTO]); impl LateLintPass<'_> for FromOverInto { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { + if !meets_msrv(self.msrv.as_ref(), &FROM_OVER_INTO_MSRV) { + return; + } + let impl_def_id = cx.tcx.hir().local_def_id(item.hir_id); if_chain! { if let hir::ItemKind::Impl{ .. } = &item.kind; @@ -55,9 +73,11 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { item.span, "An implementation of From is preferred since it gives you Into<..> for free where the reverse isn't true.", None, - "consider implement From instead", + "consider to implement From instead", ); } } } + + extract_msrv_attr!(LateContext); } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 58587481922..35b057d7b6a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1016,6 +1016,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(move || box checked_conversions::CheckedConversions::new(msrv)); store.register_late_pass(move || box mem_replace::MemReplace::new(msrv)); store.register_late_pass(move || box ranges::Ranges::new(msrv)); + store.register_late_pass(move || box from_over_into::FromOverInto::new(msrv)); store.register_late_pass(move || box use_self::UseSelf::new(msrv)); store.register_late_pass(move || box missing_const_for_fn::MissingConstForFn::new(msrv)); @@ -1205,7 +1206,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box manual_unwrap_or::ManualUnwrapOr); store.register_late_pass(|| box manual_ok_or::ManualOkOr); store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs); - store.register_late_pass(|| box from_over_into::FromOverInto); store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync); let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::>(); store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods)); diff --git a/tests/ui/from_over_into.stderr b/tests/ui/from_over_into.stderr index 17f30fa837e..c9c8e7c4b53 100644 --- a/tests/ui/from_over_into.stderr +++ b/tests/ui/from_over_into.stderr @@ -9,7 +9,7 @@ LL | | } | |_^ | = note: `-D clippy::from-over-into` implied by `-D warnings` - = help: consider implement From instead + = help: consider to implement From instead error: aborting due to previous error diff --git a/tests/ui/min_rust_version_attr.rs b/tests/ui/min_rust_version_attr.rs index 3848bca3207..0f47f1cbc40 100644 --- a/tests/ui/min_rust_version_attr.rs +++ b/tests/ui/min_rust_version_attr.rs @@ -57,6 +57,14 @@ pub fn checked_conversion() { let _ = value <= (u32::MAX as i64) && value >= 0; } +pub struct FromOverInto(String); + +impl Into for String { + fn into(self) -> FromOverInto { + FromOverInto(self) + } +} + pub fn filter_map_next() { let a = ["1", "lol", "3", "NaN", "5"]; diff --git a/tests/ui/min_rust_version_attr.stderr b/tests/ui/min_rust_version_attr.stderr index 34805263104..e3e3b335cbe 100644 --- a/tests/ui/min_rust_version_attr.stderr +++ b/tests/ui/min_rust_version_attr.stderr @@ -1,12 +1,12 @@ error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:142:24 + --> $DIR/min_rust_version_attr.rs:150:24 | LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); | ^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::manual-strip` implied by `-D warnings` note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:141:9 + --> $DIR/min_rust_version_attr.rs:149:9 | LL | if s.starts_with("hello, ") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -17,13 +17,13 @@ LL | assert_eq!(.to_uppercase(), "WORLD!"); | error: stripping a prefix manually - --> $DIR/min_rust_version_attr.rs:154:24 + --> $DIR/min_rust_version_attr.rs:162:24 | LL | assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!"); | ^^^^^^^^^^^^^^^^^^^^ | note: the prefix was tested here - --> $DIR/min_rust_version_attr.rs:153:9 + --> $DIR/min_rust_version_attr.rs:161:9 | LL | if s.starts_with("hello, ") { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^