From 9a68b0cb7e91c6e57d920e30820a86d25e76b106 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Sat, 9 Jan 2021 20:14:29 +0800 Subject: [PATCH 01/28] cargo dev new_lint. --- CHANGELOG.md | 1 + ...d_try_into_instead_of_from_and_try_from.rs | 28 +++++++++++++++++++ clippy_lints/src/lib.rs | 4 +++ ...d_try_into_instead_of_from_and_try_from.rs | 5 ++++ 4 files changed, 38 insertions(+) create mode 100644 clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs create mode 100644 tests/ui/into_and_try_into_instead_of_from_and_try_from.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index d96c74b6e412..d35dc92f098e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2125,6 +2125,7 @@ Released 2018-09-13 [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division +[`into_and_try_into_instead_of_from_and_try_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_and_try_into_instead_of_from_and_try_from [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering diff --git a/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs b/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs new file mode 100644 index 000000000000..cdb1f8c73735 --- /dev/null +++ b/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs @@ -0,0 +1,28 @@ +use rustc_lint::{LateLintPass, LateContext}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_hir::*; + +declare_clippy_lint! { + /// **What it does:** + /// + /// **Why is this bad?** + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// // example code where clippy issues a warning + /// ``` + /// Use instead: + /// ```rust + /// // example code which does not raise clippy warning + /// ``` + pub INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM, + style, + "default lint description" +} + +declare_lint_pass!(IntoAndTryIntoInsteadOfFromAndTryFrom => [INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM]); + +impl LateLintPass<'_> for IntoAndTryIntoInsteadOfFromAndTryFrom {} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d66e3720be0d..2537e8b23432 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -229,6 +229,7 @@ mod inherent_to_string; mod inline_fn_without_body; mod int_plus_one; mod integer_division; +mod into_and_try_into_instead_of_from_and_try_from; mod items_after_statements; mod large_const_arrays; mod large_enum_variant; @@ -669,6 +670,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &inline_fn_without_body::INLINE_FN_WITHOUT_BODY, &int_plus_one::INT_PLUS_ONE, &integer_division::INTEGER_DIVISION, + &into_and_try_into_instead_of_from_and_try_from::INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM, &items_after_statements::ITEMS_AFTER_STATEMENTS, &large_const_arrays::LARGE_CONST_ARRAYS, &large_enum_variant::LARGE_ENUM_VARIANT, @@ -1500,6 +1502,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(&int_plus_one::INT_PLUS_ONE), + LintId::of(&into_and_try_into_instead_of_from_and_try_from::INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM), LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS), LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(&len_zero::COMPARISON_TO_EMPTY), @@ -1747,6 +1750,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&if_let_some_result::IF_LET_SOME_RESULT), LintId::of(&inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), LintId::of(&inherent_to_string::INHERENT_TO_STRING), + LintId::of(&into_and_try_into_instead_of_from_and_try_from::INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM), LintId::of(&len_zero::COMPARISON_TO_EMPTY), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), diff --git a/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs b/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs new file mode 100644 index 000000000000..b13c549706c0 --- /dev/null +++ b/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs @@ -0,0 +1,5 @@ +#![warn(clippy::into_and_try_into_instead_of_from_and_try_from)] + +fn main() { + // test code goes here +} From ef88eacde92fbefbee14fe828272b4cba2dae195 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Sat, 9 Jan 2021 20:24:55 +0800 Subject: [PATCH 02/28] Add test. --- tests/ui/into_and_try_into_instead_of_from_and_try_from.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs b/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs index b13c549706c0..83fc253890e7 100644 --- a/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs +++ b/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs @@ -1,4 +1,9 @@ +// run-rustfix #![warn(clippy::into_and_try_into_instead_of_from_and_try_from)] +use std::convert::TryFrom; + +fn foo(a: T) where u32: From {} +fn bar(a: T) where u32: TryFrom {} fn main() { // test code goes here From 2461b29c6038ee788e87666a7db36ec75c46754f Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Sat, 9 Jan 2021 21:07:52 +0800 Subject: [PATCH 03/28] Lint declaration. --- clippy_lints/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 2537e8b23432..0c1ff880042e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1270,6 +1270,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box redundant_slicing::RedundantSlicing); store.register_late_pass(|| box from_str_radix_10::FromStrRadix10); store.register_late_pass(|| box manual_map::ManualMap); + store.register_late_pass(|| box into_and_try_into_instead_of_from_and_try_from::IntoAndTryIntoInsteadOfFromAndTryFrom); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), From 81bb1ec242c3ba390ec016055522f319d360c2b7 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 22 Jan 2021 14:31:11 +0800 Subject: [PATCH 04/28] is_diagnostic_item doesn't trigger the lint. --- ...d_try_into_instead_of_from_and_try_from.rs | 33 ++++++++++++++++++- clippy_lints/src/lib.rs | 1 + 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs b/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs index cdb1f8c73735..941e2c3d304e 100644 --- a/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs +++ b/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs @@ -1,6 +1,11 @@ +// use crate::utils::span_lint_and_help; +use crate::utils::span_lint; use rustc_lint::{LateLintPass, LateContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_hir::*; +// use rustc_span::Span; +use rustc_span::Symbol; +use if_chain::if_chain; declare_clippy_lint! { /// **What it does:** @@ -25,4 +30,30 @@ declare_clippy_lint! { declare_lint_pass!(IntoAndTryIntoInsteadOfFromAndTryFrom => [INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM]); -impl LateLintPass<'_> for IntoAndTryIntoInsteadOfFromAndTryFrom {} +impl LateLintPass<'tcx> for IntoAndTryIntoInsteadOfFromAndTryFrom { + fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, wp: &'tcx WherePredicate<'tcx>) { + match wp { + WherePredicate::BoundPredicate(wbp) => { + if_chain! { + if wbp.bounds.len() == 1; + if let Some(tr_ref) = wbp.bounds[0].trait_ref(); + if let Some(def_id) = tr_ref.trait_def_id(); + then { + ["From", "TryFrom"].map(|e| { + if cx.tcx.is_diagnostic_item(Symbol::intern(e), def_id) { + span_lint( + cx, + INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM, + wp.span(), + "What is WHERE PREDICATE" + ); + } + }); + } + } + }, + _ => (), + }; + + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0c1ff880042e..e721dfaec047 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -12,6 +12,7 @@ #![feature(rustc_private)] #![feature(stmt_expr_attributes)] #![feature(control_flow_enum)] +#![feature(array_map)] #![recursion_limit = "512"] #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![allow(clippy::missing_docs_in_private_items, clippy::must_use_candidate)] From 5d1f3884c09dc5baac433748587c62ba41e0ec07 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Sat, 23 Jan 2021 13:54:38 +0800 Subject: [PATCH 05/28] Rename lint into `into_instead_of_from`. --- CHANGELOG.md | 2 +- ...nd_try_from.rs => into_instead_of_from.rs} | 27 +++++++++---------- clippy_lints/src/lib.rs | 9 ++++--- ...nd_try_from.rs => into_instead_of_from.rs} | 3 +-- 4 files changed, 19 insertions(+), 22 deletions(-) rename clippy_lints/src/{into_and_try_into_instead_of_from_and_try_from.rs => into_instead_of_from.rs} (57%) rename tests/ui/{into_and_try_into_instead_of_from_and_try_from.rs => into_instead_of_from.rs} (59%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d35dc92f098e..0442a4d5d4bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2125,7 +2125,7 @@ Released 2018-09-13 [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division -[`into_and_try_into_instead_of_from_and_try_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_and_try_into_instead_of_from_and_try_from +[`into_instead_of_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_instead_of_from [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering diff --git a/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs b/clippy_lints/src/into_instead_of_from.rs similarity index 57% rename from clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs rename to clippy_lints/src/into_instead_of_from.rs index 941e2c3d304e..a1d5fd96b57d 100644 --- a/clippy_lints/src/into_and_try_into_instead_of_from_and_try_from.rs +++ b/clippy_lints/src/into_instead_of_from.rs @@ -4,7 +4,7 @@ use rustc_lint::{LateLintPass, LateContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_hir::*; // use rustc_span::Span; -use rustc_span::Symbol; +use rustc_span::symbol::sym; use if_chain::if_chain; declare_clippy_lint! { @@ -23,32 +23,29 @@ declare_clippy_lint! { /// ```rust /// // example code which does not raise clippy warning /// ``` - pub INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM, + pub INTO_INSTEAD_OF_FROM, style, "default lint description" } -declare_lint_pass!(IntoAndTryIntoInsteadOfFromAndTryFrom => [INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM]); +declare_lint_pass!(IntoInsteadOfFrom => [INTO_INSTEAD_OF_FROM]); -impl LateLintPass<'tcx> for IntoAndTryIntoInsteadOfFromAndTryFrom { +impl LateLintPass<'tcx> for IntoInsteadOfFrom { fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, wp: &'tcx WherePredicate<'tcx>) { match wp { WherePredicate::BoundPredicate(wbp) => { if_chain! { - if wbp.bounds.len() == 1; if let Some(tr_ref) = wbp.bounds[0].trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); then { - ["From", "TryFrom"].map(|e| { - if cx.tcx.is_diagnostic_item(Symbol::intern(e), def_id) { - span_lint( - cx, - INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM, - wp.span(), - "What is WHERE PREDICATE" - ); - } - }); + if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { + span_lint( + cx, + INTO_INSTEAD_OF_FROM, + wp.span(), + "What is WHERE PREDICATE" + ); + } } } }, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e721dfaec047..4de4cbe84c57 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -230,7 +230,7 @@ mod inherent_to_string; mod inline_fn_without_body; mod int_plus_one; mod integer_division; -mod into_and_try_into_instead_of_from_and_try_from; +mod into_instead_of_from; mod items_after_statements; mod large_const_arrays; mod large_enum_variant; @@ -671,7 +671,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &inline_fn_without_body::INLINE_FN_WITHOUT_BODY, &int_plus_one::INT_PLUS_ONE, &integer_division::INTEGER_DIVISION, - &into_and_try_into_instead_of_from_and_try_from::INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM, + &into_instead_of_from::INTO_INSTEAD_OF_FROM, &items_after_statements::ITEMS_AFTER_STATEMENTS, &large_const_arrays::LARGE_CONST_ARRAYS, &large_enum_variant::LARGE_ENUM_VARIANT, @@ -1272,6 +1272,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box from_str_radix_10::FromStrRadix10); store.register_late_pass(|| box manual_map::ManualMap); store.register_late_pass(|| box into_and_try_into_instead_of_from_and_try_from::IntoAndTryIntoInsteadOfFromAndTryFrom); + store.register_late_pass(|| box into_instead_of_from::IntoInsteadOfFrom); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1504,7 +1505,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(&int_plus_one::INT_PLUS_ONE), - LintId::of(&into_and_try_into_instead_of_from_and_try_from::INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM), + LintId::of(&into_instead_of_from::INTO_INSTEAD_OF_FROM), LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS), LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(&len_zero::COMPARISON_TO_EMPTY), @@ -1752,7 +1753,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&if_let_some_result::IF_LET_SOME_RESULT), LintId::of(&inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), LintId::of(&inherent_to_string::INHERENT_TO_STRING), - LintId::of(&into_and_try_into_instead_of_from_and_try_from::INTO_AND_TRY_INTO_INSTEAD_OF_FROM_AND_TRY_FROM), + LintId::of(&into_instead_of_from::INTO_INSTEAD_OF_FROM), LintId::of(&len_zero::COMPARISON_TO_EMPTY), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), diff --git a/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs b/tests/ui/into_instead_of_from.rs similarity index 59% rename from tests/ui/into_and_try_into_instead_of_from_and_try_from.rs rename to tests/ui/into_instead_of_from.rs index 83fc253890e7..e8ec0d54a969 100644 --- a/tests/ui/into_and_try_into_instead_of_from_and_try_from.rs +++ b/tests/ui/into_instead_of_from.rs @@ -1,10 +1,9 @@ // run-rustfix -#![warn(clippy::into_and_try_into_instead_of_from_and_try_from)] +#![warn(clippy::into_instead_of_from)] use std::convert::TryFrom; fn foo(a: T) where u32: From {} fn bar(a: T) where u32: TryFrom {} fn main() { - // test code goes here } From 90b86b589f3606bade47f528baefa64db16b5b6f Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Sat, 23 Jan 2021 14:16:12 +0800 Subject: [PATCH 06/28] Move if condiction from then block out. --- clippy_lints/src/into_instead_of_from.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/into_instead_of_from.rs b/clippy_lints/src/into_instead_of_from.rs index a1d5fd96b57d..6c825a886e24 100644 --- a/clippy_lints/src/into_instead_of_from.rs +++ b/clippy_lints/src/into_instead_of_from.rs @@ -37,15 +37,14 @@ impl LateLintPass<'tcx> for IntoInsteadOfFrom { if_chain! { if let Some(tr_ref) = wbp.bounds[0].trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); + if cx.tcx.is_diagnostic_item(sym::from_trait, def_id); then { - if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { - span_lint( - cx, - INTO_INSTEAD_OF_FROM, - wp.span(), - "What is WHERE PREDICATE" - ); - } + span_lint( + cx, + INTO_INSTEAD_OF_FROM, + wp.span(), + "What is WHERE PREDICATE" + ); } } }, From 5e5730ba9158fe536782190f1de08ed9699c80fe Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Sun, 31 Jan 2021 23:47:29 +0800 Subject: [PATCH 07/28] Fixed mistake made in rebase, test try_from_trait. --- clippy_lints/src/into_instead_of_from.rs | 22 ++++++++++++++++------ clippy_lints/src/lib.rs | 1 - 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/into_instead_of_from.rs b/clippy_lints/src/into_instead_of_from.rs index 6c825a886e24..29ed1b84de38 100644 --- a/clippy_lints/src/into_instead_of_from.rs +++ b/clippy_lints/src/into_instead_of_from.rs @@ -39,12 +39,22 @@ impl LateLintPass<'tcx> for IntoInsteadOfFrom { if let Some(def_id) = tr_ref.trait_def_id(); if cx.tcx.is_diagnostic_item(sym::from_trait, def_id); then { - span_lint( - cx, - INTO_INSTEAD_OF_FROM, - wp.span(), - "What is WHERE PREDICATE" - ); + if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { + span_lint( + cx, + INTO_INSTEAD_OF_FROM, + wp.span(), + "That is from_trait" + ); + }; + if cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) { + span_lint( + cx, + INTO_INSTEAD_OF_FROM, + wp.span(), + "That is try_from_trait" + ); + }; } } }, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 4de4cbe84c57..6aa8cbdf27bc 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1271,7 +1271,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box redundant_slicing::RedundantSlicing); store.register_late_pass(|| box from_str_radix_10::FromStrRadix10); store.register_late_pass(|| box manual_map::ManualMap); - store.register_late_pass(|| box into_and_try_into_instead_of_from_and_try_from::IntoAndTryIntoInsteadOfFromAndTryFrom); store.register_late_pass(|| box into_instead_of_from::IntoInsteadOfFrom); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ From bc9481f08d07097962c864a6b6f3e11a8713b03a Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Mon, 1 Feb 2021 00:19:14 +0800 Subject: [PATCH 08/28] Remove extra is diagnositc item check. --- clippy_lints/src/into_instead_of_from.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/clippy_lints/src/into_instead_of_from.rs b/clippy_lints/src/into_instead_of_from.rs index 29ed1b84de38..32618fb957b0 100644 --- a/clippy_lints/src/into_instead_of_from.rs +++ b/clippy_lints/src/into_instead_of_from.rs @@ -37,7 +37,6 @@ impl LateLintPass<'tcx> for IntoInsteadOfFrom { if_chain! { if let Some(tr_ref) = wbp.bounds[0].trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); - if cx.tcx.is_diagnostic_item(sym::from_trait, def_id); then { if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { span_lint( From d7c515240716c6091e3ab2e05fbb9dab1be274ae Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Tue, 2 Feb 2021 21:23:56 +0800 Subject: [PATCH 09/28] Documentation. --- clippy_lints/src/into_instead_of_from.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/into_instead_of_from.rs b/clippy_lints/src/into_instead_of_from.rs index 32618fb957b0..5c67c70b80cf 100644 --- a/clippy_lints/src/into_instead_of_from.rs +++ b/clippy_lints/src/into_instead_of_from.rs @@ -8,20 +8,25 @@ use rustc_span::symbol::sym; use if_chain::if_chain; declare_clippy_lint! { - /// **What it does:** + /// **What it does:** Checking for using of Into or TryInto trait as a generic bound. /// - /// **Why is this bad?** + /// **Why is this bad?** Into and TryInto are supersets of From and TryFrom. Due to + /// coherence rules, sometimes Into and TryInto are forbid to implemented but From and + /// TryFrom are not. So Into is a more generic bound than From, We should choose Into or + /// TryInto instead of From or TryFrom. /// /// **Known problems:** None. /// /// **Example:** /// /// ```rust - /// // example code where clippy issues a warning + /// fn foo(a: T) where u32: From {} + /// fn bar(a: T) where u32: TryFrom {} /// ``` /// Use instead: /// ```rust - /// // example code which does not raise clippy warning + /// fn foo(a: T) where T: Into {} + /// fn bar(a: T) where T: TryFrom {} /// ``` pub INTO_INSTEAD_OF_FROM, style, From d7822db87bda1f8ee1ffb16dc40da9ce42cd1fd0 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Tue, 2 Feb 2021 21:47:37 +0800 Subject: [PATCH 10/28] Waiting to fill sugg. --- clippy_lints/src/into_instead_of_from.rs | 28 +++++++++++++++--------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/into_instead_of_from.rs b/clippy_lints/src/into_instead_of_from.rs index 5c67c70b80cf..0d5a05f54b40 100644 --- a/clippy_lints/src/into_instead_of_from.rs +++ b/clippy_lints/src/into_instead_of_from.rs @@ -1,5 +1,5 @@ // use crate::utils::span_lint_and_help; -use crate::utils::span_lint; +use crate::utils::span_lint_and_sugg; use rustc_lint::{LateLintPass, LateContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_hir::*; @@ -8,11 +8,11 @@ use rustc_span::symbol::sym; use if_chain::if_chain; declare_clippy_lint! { - /// **What it does:** Checking for using of Into or TryInto trait as a generic bound. + /// **What it does:** Checking for using of From or TryFrom trait as a generic bound. /// /// **Why is this bad?** Into and TryInto are supersets of From and TryFrom. Due to - /// coherence rules, sometimes Into and TryInto are forbid to implemented but From and - /// TryFrom are not. So Into is a more generic bound than From, We should choose Into or + /// coherence rules, sometimes From and TryFrom are forbid to implemented but Into and + /// TryInto are not. So Into is a more generic bound than From, We should choose Into or /// TryInto instead of From or TryFrom. /// /// **Known problems:** None. @@ -26,11 +26,11 @@ declare_clippy_lint! { /// Use instead: /// ```rust /// fn foo(a: T) where T: Into {} - /// fn bar(a: T) where T: TryFrom {} + /// fn bar(a: T) where T: TryInto {} /// ``` pub INTO_INSTEAD_OF_FROM, style, - "default lint description" + "Into or TryInto trait is a better choice than From or TryFrom trait as a generic bound" } declare_lint_pass!(IntoInsteadOfFrom => [INTO_INSTEAD_OF_FROM]); @@ -44,19 +44,27 @@ impl LateLintPass<'tcx> for IntoInsteadOfFrom { if let Some(def_id) = tr_ref.trait_def_id(); then { if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { - span_lint( + let sugg = ""; //Todo + span_lint_and_sugg( cx, INTO_INSTEAD_OF_FROM, wp.span(), - "That is from_trait" + "Into trait is a more preferable choice than From as a generic bound", + format!("try `{}` instead", sugg), + sugg, + Applicability::MachineApplicable ); }; if cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) { - span_lint( + let sugg = ""; //Todo + span_lint_and_sugg( cx, INTO_INSTEAD_OF_FROM, wp.span(), - "That is try_from_trait" + "TryInto trait is a more preferable choice than TryFrom as a generic bound", + format!("try `{}` instead", sugg), + sugg, + Applicability::MachineApplicable ); }; } From d0d369822295f5b3b0a6302bd9b23b19763a7984 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 12 Feb 2021 21:51:14 +0800 Subject: [PATCH 11/28] Emit suggestion. --- clippy_lints/src/into_instead_of_from.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/into_instead_of_from.rs b/clippy_lints/src/into_instead_of_from.rs index 0d5a05f54b40..000605b60cc7 100644 --- a/clippy_lints/src/into_instead_of_from.rs +++ b/clippy_lints/src/into_instead_of_from.rs @@ -1,9 +1,9 @@ -// use crate::utils::span_lint_and_help; use crate::utils::span_lint_and_sugg; +use crate::utils::snippet; +use rustc_errors::Applicability; use rustc_lint::{LateLintPass, LateContext}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_hir::*; -// use rustc_span::Span; use rustc_span::symbol::sym; use if_chain::if_chain; @@ -42,27 +42,33 @@ impl LateLintPass<'tcx> for IntoInsteadOfFrom { if_chain! { if let Some(tr_ref) = wbp.bounds[0].trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); + if let Some(last_seg) = tr_ref.path.segments.last(); + if let Some(generic_arg) = last_seg.args().args.first(); then { + let bounded_ty = snippet(cx, wbp.bounded_ty.span, ".."); + let generic_arg_of_from_or_try_from = snippet(cx, generic_arg.span(), ".."); + if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { - let sugg = ""; //Todo + let sugg = format!("{}: Into<{}>", generic_arg_of_from_or_try_from, bounded_ty); span_lint_and_sugg( cx, INTO_INSTEAD_OF_FROM, wp.span(), "Into trait is a more preferable choice than From as a generic bound", - format!("try `{}` instead", sugg), + "try", sugg, Applicability::MachineApplicable ); }; + if cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) { - let sugg = ""; //Todo + let sugg = format!("{}: TryInto<{}>", generic_arg_of_from_or_try_from, bounded_ty); span_lint_and_sugg( cx, INTO_INSTEAD_OF_FROM, wp.span(), "TryInto trait is a more preferable choice than TryFrom as a generic bound", - format!("try `{}` instead", sugg), + "try", sugg, Applicability::MachineApplicable ); From e4013af999ffaad14c833a802ab0dcfe08c80adb Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 12 Feb 2021 22:07:15 +0800 Subject: [PATCH 12/28] Rename lint. --- CHANGELOG.md | 2 +- ..._instead_of_from.rs => from_instead_of_into.rs} | 14 +++++++------- clippy_lints/src/lib.rs | 10 +++++----- ..._instead_of_from.rs => from_instead_of_into.rs} | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) rename clippy_lints/src/{into_instead_of_from.rs => from_instead_of_into.rs} (86%) rename tests/ui/{into_instead_of_from.rs => from_instead_of_into.rs} (77%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0442a4d5d4bd..52def91519b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2125,7 +2125,7 @@ Released 2018-09-13 [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division -[`into_instead_of_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_instead_of_from +[`from_instead_of_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_instead_of_into [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering diff --git a/clippy_lints/src/into_instead_of_from.rs b/clippy_lints/src/from_instead_of_into.rs similarity index 86% rename from clippy_lints/src/into_instead_of_from.rs rename to clippy_lints/src/from_instead_of_into.rs index 000605b60cc7..4b881cf0d278 100644 --- a/clippy_lints/src/into_instead_of_from.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -28,14 +28,14 @@ declare_clippy_lint! { /// fn foo(a: T) where T: Into {} /// fn bar(a: T) where T: TryInto {} /// ``` - pub INTO_INSTEAD_OF_FROM, + pub FROM_INSTEAD_OF_INTO, style, "Into or TryInto trait is a better choice than From or TryFrom trait as a generic bound" } -declare_lint_pass!(IntoInsteadOfFrom => [INTO_INSTEAD_OF_FROM]); +declare_lint_pass!(FromInsteadOfInto => [FROM_INSTEAD_OF_INTO]); -impl LateLintPass<'tcx> for IntoInsteadOfFrom { +impl LateLintPass<'tcx> for FromInsteadOfInto { fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, wp: &'tcx WherePredicate<'tcx>) { match wp { WherePredicate::BoundPredicate(wbp) => { @@ -52,9 +52,9 @@ impl LateLintPass<'tcx> for IntoInsteadOfFrom { let sugg = format!("{}: Into<{}>", generic_arg_of_from_or_try_from, bounded_ty); span_lint_and_sugg( cx, - INTO_INSTEAD_OF_FROM, + FROM_INSTEAD_OF_INTO, wp.span(), - "Into trait is a more preferable choice than From as a generic bound", + "Into trait is preferable than From as a generic bound", "try", sugg, Applicability::MachineApplicable @@ -65,9 +65,9 @@ impl LateLintPass<'tcx> for IntoInsteadOfFrom { let sugg = format!("{}: TryInto<{}>", generic_arg_of_from_or_try_from, bounded_ty); span_lint_and_sugg( cx, - INTO_INSTEAD_OF_FROM, + FROM_INSTEAD_OF_INTO, wp.span(), - "TryInto trait is a more preferable choice than TryFrom as a generic bound", + "TryInto trait is preferable than TryFrom as a generic bound", "try", sugg, Applicability::MachineApplicable diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6aa8cbdf27bc..b2835645dcae 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -230,7 +230,7 @@ mod inherent_to_string; mod inline_fn_without_body; mod int_plus_one; mod integer_division; -mod into_instead_of_from; +mod from_instead_of_into; mod items_after_statements; mod large_const_arrays; mod large_enum_variant; @@ -671,7 +671,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &inline_fn_without_body::INLINE_FN_WITHOUT_BODY, &int_plus_one::INT_PLUS_ONE, &integer_division::INTEGER_DIVISION, - &into_instead_of_from::INTO_INSTEAD_OF_FROM, + &from_instead_of_into::FROM_INSTEAD_OF_INTO, &items_after_statements::ITEMS_AFTER_STATEMENTS, &large_const_arrays::LARGE_CONST_ARRAYS, &large_enum_variant::LARGE_ENUM_VARIANT, @@ -1271,7 +1271,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box redundant_slicing::RedundantSlicing); store.register_late_pass(|| box from_str_radix_10::FromStrRadix10); store.register_late_pass(|| box manual_map::ManualMap); - store.register_late_pass(|| box into_instead_of_from::IntoInsteadOfFrom); + store.register_late_pass(|| box from_instead_of_into::FromInsteadOfInto); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1504,7 +1504,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(&int_plus_one::INT_PLUS_ONE), - LintId::of(&into_instead_of_from::INTO_INSTEAD_OF_FROM), + LintId::of(&from_instead_of_into::FROM_INSTEAD_OF_INTO), LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS), LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(&len_zero::COMPARISON_TO_EMPTY), @@ -1752,7 +1752,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&if_let_some_result::IF_LET_SOME_RESULT), LintId::of(&inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), LintId::of(&inherent_to_string::INHERENT_TO_STRING), - LintId::of(&into_instead_of_from::INTO_INSTEAD_OF_FROM), + LintId::of(&from_instead_of_into::FROM_INSTEAD_OF_INTO), LintId::of(&len_zero::COMPARISON_TO_EMPTY), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), diff --git a/tests/ui/into_instead_of_from.rs b/tests/ui/from_instead_of_into.rs similarity index 77% rename from tests/ui/into_instead_of_from.rs rename to tests/ui/from_instead_of_into.rs index e8ec0d54a969..ec359e9da74c 100644 --- a/tests/ui/into_instead_of_from.rs +++ b/tests/ui/from_instead_of_into.rs @@ -1,5 +1,5 @@ // run-rustfix -#![warn(clippy::into_instead_of_from)] +#![warn(clippy::from_instead_of_into)] use std::convert::TryFrom; fn foo(a: T) where u32: From {} From 3d8a1ea82b25f113398ff73e7d5cb114e3fed98f Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 12 Feb 2021 22:10:19 +0800 Subject: [PATCH 13/28] Satisfy with test. --- tests/ui/from_instead_of_into.fixed | 9 +++++++++ tests/ui/from_instead_of_into.stderr | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/ui/from_instead_of_into.fixed create mode 100644 tests/ui/from_instead_of_into.stderr diff --git a/tests/ui/from_instead_of_into.fixed b/tests/ui/from_instead_of_into.fixed new file mode 100644 index 000000000000..aefce212c478 --- /dev/null +++ b/tests/ui/from_instead_of_into.fixed @@ -0,0 +1,9 @@ +// run-rustfix +#![warn(clippy::from_instead_of_into)] +use std::convert::TryFrom; + +fn foo(a: T) where T: Into {} +fn bar(a: T) where T: TryInto {} + +fn main() { +} diff --git a/tests/ui/from_instead_of_into.stderr b/tests/ui/from_instead_of_into.stderr new file mode 100644 index 000000000000..85902f85198b --- /dev/null +++ b/tests/ui/from_instead_of_into.stderr @@ -0,0 +1,16 @@ +error: Into trait is preferable than From as a generic bound + --> $DIR/from_instead_of_into.rs:5:23 + | +LL | fn foo(a: T) where u32: From {} + | ^^^^^^^^^^^^ help: try: `T: Into` + | + = note: `-D clippy::from-instead-of-into` implied by `-D warnings` + +error: TryInto trait is preferable than TryFrom as a generic bound + --> $DIR/from_instead_of_into.rs:6:23 + | +LL | fn bar(a: T) where u32: TryFrom {} + | ^^^^^^^^^^^^^^^ help: try: `T: TryInto` + +error: aborting due to 2 previous errors + From 62ab8da8e9ba5cbd11b503b0f47155e34c0b9bbd Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 12 Feb 2021 22:17:58 +0800 Subject: [PATCH 14/28] Update lints. --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52def91519b9..573bedfebd65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2091,6 +2091,7 @@ Released 2018-09-13 [`for_loops_over_fallibles`]: https://rust-lang.github.io/rust-clippy/master/index.html#for_loops_over_fallibles [`forget_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_copy [`forget_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#forget_ref +[`from_instead_of_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_instead_of_into [`from_iter_instead_of_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_iter_instead_of_collect [`from_over_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_over_into [`from_str_radix_10`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_str_radix_10 @@ -2125,7 +2126,6 @@ Released 2018-09-13 [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division -[`from_instead_of_into`]: https://rust-lang.github.io/rust-clippy/master/index.html#from_instead_of_into [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b2835645dcae..5f04f4a8860a 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -211,6 +211,7 @@ mod float_literal; mod floating_point_arithmetic; mod format; mod formatting; +mod from_instead_of_into; mod from_over_into; mod from_str_radix_10; mod functions; @@ -230,7 +231,6 @@ mod inherent_to_string; mod inline_fn_without_body; mod int_plus_one; mod integer_division; -mod from_instead_of_into; mod items_after_statements; mod large_const_arrays; mod large_enum_variant; @@ -643,6 +643,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, &formatting::SUSPICIOUS_ELSE_FORMATTING, &formatting::SUSPICIOUS_UNARY_OP_FORMATTING, + &from_instead_of_into::FROM_INSTEAD_OF_INTO, &from_over_into::FROM_OVER_INTO, &from_str_radix_10::FROM_STR_RADIX_10, &functions::DOUBLE_MUST_USE, @@ -671,7 +672,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &inline_fn_without_body::INLINE_FN_WITHOUT_BODY, &int_plus_one::INT_PLUS_ONE, &integer_division::INTEGER_DIVISION, - &from_instead_of_into::FROM_INSTEAD_OF_INTO, &items_after_statements::ITEMS_AFTER_STATEMENTS, &large_const_arrays::LARGE_CONST_ARRAYS, &large_enum_variant::LARGE_ENUM_VARIANT, @@ -1486,6 +1486,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING), LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING), + LintId::of(&from_instead_of_into::FROM_INSTEAD_OF_INTO), LintId::of(&from_over_into::FROM_OVER_INTO), LintId::of(&from_str_radix_10::FROM_STR_RADIX_10), LintId::of(&functions::DOUBLE_MUST_USE), @@ -1504,7 +1505,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY), LintId::of(&inline_fn_without_body::INLINE_FN_WITHOUT_BODY), LintId::of(&int_plus_one::INT_PLUS_ONE), - LintId::of(&from_instead_of_into::FROM_INSTEAD_OF_INTO), LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS), LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT), LintId::of(&len_zero::COMPARISON_TO_EMPTY), @@ -1744,6 +1744,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING), LintId::of(&formatting::SUSPICIOUS_ELSE_FORMATTING), LintId::of(&formatting::SUSPICIOUS_UNARY_OP_FORMATTING), + LintId::of(&from_instead_of_into::FROM_INSTEAD_OF_INTO), LintId::of(&from_over_into::FROM_OVER_INTO), LintId::of(&from_str_radix_10::FROM_STR_RADIX_10), LintId::of(&functions::DOUBLE_MUST_USE), @@ -1752,7 +1753,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&if_let_some_result::IF_LET_SOME_RESULT), LintId::of(&inconsistent_struct_constructor::INCONSISTENT_STRUCT_CONSTRUCTOR), LintId::of(&inherent_to_string::INHERENT_TO_STRING), - LintId::of(&from_instead_of_into::FROM_INSTEAD_OF_INTO), LintId::of(&len_zero::COMPARISON_TO_EMPTY), LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY), LintId::of(&len_zero::LEN_ZERO), From b04f8a136d893fdc0170efe4456517bf14fb0213 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 12 Feb 2021 22:44:44 +0800 Subject: [PATCH 15/28] cargo dev fmt. --- clippy_lints/src/from_instead_of_into.rs | 13 ++++++------- tests/ui/from_instead_of_into.rs | 15 +++++++++++---- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index 4b881cf0d278..bf2da5905e15 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -1,17 +1,17 @@ -use crate::utils::span_lint_and_sugg; use crate::utils::snippet; +use crate::utils::span_lint_and_sugg; +use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_lint::{LateLintPass, LateContext}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_hir::*; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; -use if_chain::if_chain; declare_clippy_lint! { /// **What it does:** Checking for using of From or TryFrom trait as a generic bound. /// - /// **Why is this bad?** Into and TryInto are supersets of From and TryFrom. Due to - /// coherence rules, sometimes From and TryFrom are forbid to implemented but Into and + /// **Why is this bad?** Into and TryInto are supersets of From and TryFrom. Due to + /// coherence rules, sometimes From and TryFrom are forbid to implemented but Into and /// TryInto are not. So Into is a more generic bound than From, We should choose Into or /// TryInto instead of From or TryFrom. /// @@ -78,6 +78,5 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { }, _ => (), }; - } } diff --git a/tests/ui/from_instead_of_into.rs b/tests/ui/from_instead_of_into.rs index ec359e9da74c..b1517e9d099a 100644 --- a/tests/ui/from_instead_of_into.rs +++ b/tests/ui/from_instead_of_into.rs @@ -2,8 +2,15 @@ #![warn(clippy::from_instead_of_into)] use std::convert::TryFrom; -fn foo(a: T) where u32: From {} -fn bar(a: T) where u32: TryFrom {} - -fn main() { +fn foo(a: T) +where + u32: From, +{ +} +fn bar(a: T) +where + u32: TryFrom, +{ } + +fn main() {} From 72e4786241780c5e55c52170898850c7f21e8eed Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 12 Feb 2021 23:24:20 +0800 Subject: [PATCH 16/28] Update test files after fmt. --- tests/ui/from_instead_of_into.fixed | 15 +++++++++++---- tests/ui/from_instead_of_into.stderr | 12 ++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/tests/ui/from_instead_of_into.fixed b/tests/ui/from_instead_of_into.fixed index aefce212c478..3d3440c70884 100644 --- a/tests/ui/from_instead_of_into.fixed +++ b/tests/ui/from_instead_of_into.fixed @@ -2,8 +2,15 @@ #![warn(clippy::from_instead_of_into)] use std::convert::TryFrom; -fn foo(a: T) where T: Into {} -fn bar(a: T) where T: TryInto {} - -fn main() { +fn foo(a: T) +where + T: Into, +{ +} +fn bar(a: T) +where + T: TryInto, +{ } + +fn main() {} diff --git a/tests/ui/from_instead_of_into.stderr b/tests/ui/from_instead_of_into.stderr index 85902f85198b..39184b4931cc 100644 --- a/tests/ui/from_instead_of_into.stderr +++ b/tests/ui/from_instead_of_into.stderr @@ -1,16 +1,16 @@ error: Into trait is preferable than From as a generic bound - --> $DIR/from_instead_of_into.rs:5:23 + --> $DIR/from_instead_of_into.rs:7:5 | -LL | fn foo(a: T) where u32: From {} - | ^^^^^^^^^^^^ help: try: `T: Into` +LL | u32: From, + | ^^^^^^^^^^^^ help: try: `T: Into` | = note: `-D clippy::from-instead-of-into` implied by `-D warnings` error: TryInto trait is preferable than TryFrom as a generic bound - --> $DIR/from_instead_of_into.rs:6:23 + --> $DIR/from_instead_of_into.rs:12:5 | -LL | fn bar(a: T) where u32: TryFrom {} - | ^^^^^^^^^^^^^^^ help: try: `T: TryInto` +LL | u32: TryFrom, + | ^^^^^^^^^^^^^^^ help: try: `T: TryInto` error: aborting due to 2 previous errors From c4cae209ba9c974edd2041fccb42fb378d3b702d Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Sat, 13 Feb 2021 14:46:54 +0800 Subject: [PATCH 17/28] Using From trait in this test is irrelevant. --- tests/ui/needless_question_mark.fixed | 1 + tests/ui/needless_question_mark.rs | 1 + tests/ui/needless_question_mark.stderr | 6 +++--- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/ui/needless_question_mark.fixed b/tests/ui/needless_question_mark.fixed index 71fb3565224e..0136e2b4cbdf 100644 --- a/tests/ui/needless_question_mark.fixed +++ b/tests/ui/needless_question_mark.fixed @@ -87,6 +87,7 @@ fn also_bad(tr: Result) -> Result { Err(false) } +#[allow(clippy::from_instead_of_into)] fn false_positive_test(x: Result<(), U>) -> Result<(), T> where T: From, diff --git a/tests/ui/needless_question_mark.rs b/tests/ui/needless_question_mark.rs index e31f6f48fa7c..f43705f397f5 100644 --- a/tests/ui/needless_question_mark.rs +++ b/tests/ui/needless_question_mark.rs @@ -87,6 +87,7 @@ fn also_bad(tr: Result) -> Result { Err(false) } +#[allow(clippy::from_instead_of_into)] fn false_positive_test(x: Result<(), U>) -> Result<(), T> where T: From, diff --git a/tests/ui/needless_question_mark.stderr b/tests/ui/needless_question_mark.stderr index 567bc518a3fd..6237d44e3423 100644 --- a/tests/ui/needless_question_mark.stderr +++ b/tests/ui/needless_question_mark.stderr @@ -67,19 +67,19 @@ LL | return Ok(t.magic?); | ^^^^^^^^^^^^ help: try: `t.magic` error: Question mark operator is useless here - --> $DIR/needless_question_mark.rs:138:9 + --> $DIR/needless_question_mark.rs:139:9 | LL | Ok(to.magic?) // should be triggered | ^^^^^^^^^^^^^ help: try: `to.magic` error: Question mark operator is useless here - --> $DIR/needless_question_mark.rs:154:9 + --> $DIR/needless_question_mark.rs:155:9 | LL | Some(to.magic?) // should be triggered | ^^^^^^^^^^^^^^^ help: try: `to.magic` error: Question mark operator is useless here - --> $DIR/needless_question_mark.rs:162:9 + --> $DIR/needless_question_mark.rs:163:9 | LL | Ok(to.magic?) // should be triggered | ^^^^^^^^^^^^^ help: try: `to.magic` From 236b82e7437cd48ab1e0f884bee0ed6c564ae6b8 Mon Sep 17 00:00:00 2001 From: Rui Date: Sun, 14 Feb 2021 23:42:22 +0800 Subject: [PATCH 18/28] Suggestion may be incorrect. Co-authored-by: Philipp Krones --- clippy_lints/src/from_instead_of_into.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index bf2da5905e15..44a1d06ac61e 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -70,7 +70,7 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { "TryInto trait is preferable than TryFrom as a generic bound", "try", sugg, - Applicability::MachineApplicable + Applicability::MaybeIncorrect ); }; } From 95c112316f245511ec991e35dd7a5a69536c4e11 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Wed, 17 Feb 2021 18:22:19 +0800 Subject: [PATCH 19/28] Migrate to use find. --- clippy_lints/src/from_instead_of_into.rs | 44 +++++++++++++++--------- tests/ui/from_instead_of_into.rs | 1 + 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index 44a1d06ac61e..265050268e72 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -40,7 +40,21 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { match wp { WherePredicate::BoundPredicate(wbp) => { if_chain! { - if let Some(tr_ref) = wbp.bounds[0].trait_ref(); + if let Some(target_bound) = wbp.bounds.iter().find(|b| { + if_chain! { + if let Some(r) = b.trait_ref(); + if let Some(def_id) = r.trait_def_id(); + then { + cx.tcx.is_diagnostic_item(sym::from_trait, def_id) || + cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) + } else { + false + } + } + }); + // if let Some(tr_ref) = wbp.bounds[0].trait_ref(); + if wbp.bounds.len() == 1; + if let Some(tr_ref) = target_bound.trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); if let Some(last_seg) = tr_ref.path.segments.last(); if let Some(generic_arg) = last_seg.args().args.first(); @@ -48,31 +62,29 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { let bounded_ty = snippet(cx, wbp.bounded_ty.span, ".."); let generic_arg_of_from_or_try_from = snippet(cx, generic_arg.span(), ".."); + let mut replace_trait_name = ""; + let mut target_trait_name = ""; if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { - let sugg = format!("{}: Into<{}>", generic_arg_of_from_or_try_from, bounded_ty); - span_lint_and_sugg( - cx, - FROM_INSTEAD_OF_INTO, - wp.span(), - "Into trait is preferable than From as a generic bound", - "try", - sugg, - Applicability::MachineApplicable - ); - }; + replace_trait_name = "Into"; + target_trait_name = "From"; + } else if cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) { + replace_trait_name = "TryInto"; + target_trait_name = "TryFrom"; + } - if cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) { - let sugg = format!("{}: TryInto<{}>", generic_arg_of_from_or_try_from, bounded_ty); + if !replace_trait_name.is_empty() && !target_trait_name.is_empty() { + let message = format!("{} trait is preferable than {} as a generic bound", replace_trait_name, target_trait_name); + let sugg = format!("{}: {}<{}>", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); span_lint_and_sugg( cx, FROM_INSTEAD_OF_INTO, wp.span(), - "TryInto trait is preferable than TryFrom as a generic bound", + &message, "try", sugg, Applicability::MaybeIncorrect ); - }; + } } } }, diff --git a/tests/ui/from_instead_of_into.rs b/tests/ui/from_instead_of_into.rs index b1517e9d099a..58310c261ccd 100644 --- a/tests/ui/from_instead_of_into.rs +++ b/tests/ui/from_instead_of_into.rs @@ -1,4 +1,5 @@ // run-rustfix +#![allow(unused_imports)] #![warn(clippy::from_instead_of_into)] use std::convert::TryFrom; From 867a07f124b74a09a8cde7cbff5a51d37ef1d4bf Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Wed, 17 Feb 2021 19:10:31 +0800 Subject: [PATCH 20/28] Work with multiply bounds now. --- clippy_lints/src/from_instead_of_into.rs | 16 +++++++++++++--- tests/ui/from_instead_of_into.rs | 12 ++++++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index 265050268e72..ad682af82642 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -1,5 +1,6 @@ use crate::utils::snippet; use crate::utils::span_lint_and_sugg; +use std::ptr; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::*; @@ -52,12 +53,11 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { } } }); - // if let Some(tr_ref) = wbp.bounds[0].trait_ref(); - if wbp.bounds.len() == 1; if let Some(tr_ref) = target_bound.trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); if let Some(last_seg) = tr_ref.path.segments.last(); if let Some(generic_arg) = last_seg.args().args.first(); + if wbp.bounds.len() == 1; then { let bounded_ty = snippet(cx, wbp.bounded_ty.span, ".."); let generic_arg_of_from_or_try_from = snippet(cx, generic_arg.span(), ".."); @@ -74,7 +74,17 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { if !replace_trait_name.is_empty() && !target_trait_name.is_empty() { let message = format!("{} trait is preferable than {} as a generic bound", replace_trait_name, target_trait_name); - let sugg = format!("{}: {}<{}>", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); + let extracted_where_predicate = format!("{}: {}<{}>,", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); + let sugg; + if wbp.bounds.len() == 1 { + sugg = extracted_where_predicate; + } else { + let bounds: &[&GenericBound<'_>] = wbp.bounds.iter().filter(|b| ptr::eq(*b, target_bound)).collect(); + let bounds = bounds.map(|b| snippet(cx, b.span(), "..")); + let first = bounds[0].to_string(); + let bounds_str = bounds[1..].fold(first, |s, &e| s + " + " + snippet(cx, e.span(), "..")); + sugg = format!("{} {}: {}", extracted_where_predicate, bounded_ty, bounds_str); + } span_lint_and_sugg( cx, FROM_INSTEAD_OF_INTO, diff --git a/tests/ui/from_instead_of_into.rs b/tests/ui/from_instead_of_into.rs index 58310c261ccd..bc85a82915b1 100644 --- a/tests/ui/from_instead_of_into.rs +++ b/tests/ui/from_instead_of_into.rs @@ -8,10 +8,22 @@ where u32: From, { } + +fn foo1(a: T) +where u32: Copy + Clone + From, +{ +} + fn bar(a: T) where u32: TryFrom, { } +fn bar1(a: T) +where + u32: Copy + Clone + TryFrom, +{ +} + fn main() {} From cf542a2b660d342ddaa921dffb164433424b4836 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Thu, 18 Feb 2021 15:07:53 +0800 Subject: [PATCH 21/28] Update due to review suggestion. --- clippy_lints/src/from_instead_of_into.rs | 37 +++++++++++++----------- tests/ui/from_instead_of_into.rs | 2 +- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index ad682af82642..579695a9e501 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -38,38 +38,41 @@ declare_lint_pass!(FromInsteadOfInto => [FROM_INSTEAD_OF_INTO]); impl LateLintPass<'tcx> for FromInsteadOfInto { fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, wp: &'tcx WherePredicate<'tcx>) { + let is_target_generic_bound = |b| { + if_chain! { + if let Some(r) = b.trait_ref(); + if let Some(def_id) = r.trait_def_id(); + then { + cx.tcx.is_diagnostic_item(sym::from_trait, def_id) || + cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) + } else { + false + } + } + }; match wp { WherePredicate::BoundPredicate(wbp) => { if_chain! { - if let Some(target_bound) = wbp.bounds.iter().find(|b| { - if_chain! { - if let Some(r) = b.trait_ref(); - if let Some(def_id) = r.trait_def_id(); - then { - cx.tcx.is_diagnostic_item(sym::from_trait, def_id) || - cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) - } else { - false - } - } - }); + if let Some(target_bound) = wbp.bounds.iter().find(|b| is_target_generic_bound(b)); if let Some(tr_ref) = target_bound.trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); if let Some(last_seg) = tr_ref.path.segments.last(); if let Some(generic_arg) = last_seg.args().args.first(); + if let Some(bounded_ty) = snippet_opt(cx, wbp.bounded_ty.span); + if let Some(generic_arg_of_from_or_try_from) = snippet_opt(cx, generic_arg.span()); if wbp.bounds.len() == 1; then { - let bounded_ty = snippet(cx, wbp.bounded_ty.span, ".."); - let generic_arg_of_from_or_try_from = snippet(cx, generic_arg.span(), ".."); - - let mut replace_trait_name = ""; - let mut target_trait_name = ""; + let replace_trait_name; + let target_trait_name; if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { replace_trait_name = "Into"; target_trait_name = "From"; } else if cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) { replace_trait_name = "TryInto"; target_trait_name = "TryFrom"; + } else { + replace_trait_name = ""; + target_trait_name = ""; } if !replace_trait_name.is_empty() && !target_trait_name.is_empty() { diff --git a/tests/ui/from_instead_of_into.rs b/tests/ui/from_instead_of_into.rs index bc85a82915b1..9e958951ebe2 100644 --- a/tests/ui/from_instead_of_into.rs +++ b/tests/ui/from_instead_of_into.rs @@ -22,7 +22,7 @@ where fn bar1(a: T) where - u32: Copy + Clone + TryFrom, + u32: Copy + TryFrom + Clone, { } From 32d4643e189194ebb169bb6395d8e2ab4045416f Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Thu, 18 Feb 2021 15:14:36 +0800 Subject: [PATCH 22/28] Fix wrong filter closure. --- clippy_lints/src/from_instead_of_into.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index 579695a9e501..04460c29e34d 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -82,7 +82,7 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { if wbp.bounds.len() == 1 { sugg = extracted_where_predicate; } else { - let bounds: &[&GenericBound<'_>] = wbp.bounds.iter().filter(|b| ptr::eq(*b, target_bound)).collect(); + let bounds: &[&GenericBound<'_>] = wbp.bounds.iter().filter(|b| !ptr::eq(*b, target_bound)).collect(); let bounds = bounds.map(|b| snippet(cx, b.span(), "..")); let first = bounds[0].to_string(); let bounds_str = bounds[1..].fold(first, |s, &e| s + " + " + snippet(cx, e.span(), "..")); From 04b00eabc2c0c05f2460e76b633a0d8cdd3a1e25 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 19 Feb 2021 17:24:49 +0800 Subject: [PATCH 23/28] Finish lint logic, add 1 more case for test. --- clippy_lints/src/from_instead_of_into.rs | 54 +++++++++++++++++------- tests/ui/from_instead_of_into.fixed | 20 +++++++++ tests/ui/from_instead_of_into.rs | 10 ++++- tests/ui/from_instead_of_into.stderr | 24 +++++++++-- 4 files changed, 89 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index 04460c29e34d..dd3dc2a4c701 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -1,6 +1,5 @@ -use crate::utils::snippet; use crate::utils::span_lint_and_sugg; -use std::ptr; +use crate::utils::{snippet, snippet_opt}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::*; @@ -38,29 +37,31 @@ declare_lint_pass!(FromInsteadOfInto => [FROM_INSTEAD_OF_INTO]); impl LateLintPass<'tcx> for FromInsteadOfInto { fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, wp: &'tcx WherePredicate<'tcx>) { - let is_target_generic_bound = |b| { + let is_target_generic_bound = |b: &GenericBound<'_>| { if_chain! { if let Some(r) = b.trait_ref(); if let Some(def_id) = r.trait_def_id(); then { - cx.tcx.is_diagnostic_item(sym::from_trait, def_id) || - cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) + cx.tcx.is_diagnostic_item(sym::from_trait, def_id) || + cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) } else { false } - } + } }; match wp { WherePredicate::BoundPredicate(wbp) => { if_chain! { - if let Some(target_bound) = wbp.bounds.iter().find(|b| is_target_generic_bound(b)); + let bounds = wbp.bounds; + if let Some(position) = bounds.iter().position(|b| is_target_generic_bound(b)); + let target_bound = &bounds[position]; if let Some(tr_ref) = target_bound.trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); if let Some(last_seg) = tr_ref.path.segments.last(); if let Some(generic_arg) = last_seg.args().args.first(); if let Some(bounded_ty) = snippet_opt(cx, wbp.bounded_ty.span); if let Some(generic_arg_of_from_or_try_from) = snippet_opt(cx, generic_arg.span()); - if wbp.bounds.len() == 1; + // if wbp.bounds.len() == 1; then { let replace_trait_name; let target_trait_name; @@ -77,16 +78,39 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { if !replace_trait_name.is_empty() && !target_trait_name.is_empty() { let message = format!("{} trait is preferable than {} as a generic bound", replace_trait_name, target_trait_name); - let extracted_where_predicate = format!("{}: {}<{}>,", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); + + let extracted_where_predicate = format!("{}: {}<{}>", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); let sugg; - if wbp.bounds.len() == 1 { + if bounds.len() == 1 { sugg = extracted_where_predicate; } else { - let bounds: &[&GenericBound<'_>] = wbp.bounds.iter().filter(|b| !ptr::eq(*b, target_bound)).collect(); - let bounds = bounds.map(|b| snippet(cx, b.span(), "..")); - let first = bounds[0].to_string(); - let bounds_str = bounds[1..].fold(first, |s, &e| s + " + " + snippet(cx, e.span(), "..")); - sugg = format!("{} {}: {}", extracted_where_predicate, bounded_ty, bounds_str); + let before; + if position == 0 { + before = None; + } else { + let first_bound = &bounds[0]; + let previous_bound = &bounds[position-1]; + before = Some(snippet(cx, first_bound.span().with_hi(previous_bound.span().hi()), "..")); + } + + let after; + let last_position = bounds.len() - 1; + if position == last_position { + after = None; + } else { + let last_bound = &bounds[last_position]; + let after_bound = &bounds[position + 1]; + after = Some(snippet(cx, after_bound.span().with_hi(last_bound.span().hi()), "..")); + } + + let bounds_str = match (before, after) { + (None, None) => unreachable!(), + (Some(b), None) => b, + (None, Some(a)) => a, + (Some(b), Some(a)) => b + " + " + a, + }; + + sugg = format!("{}, {}: {}", extracted_where_predicate, bounded_ty, bounds_str); } span_lint_and_sugg( cx, diff --git a/tests/ui/from_instead_of_into.fixed b/tests/ui/from_instead_of_into.fixed index 3d3440c70884..62722f3685cc 100644 --- a/tests/ui/from_instead_of_into.fixed +++ b/tests/ui/from_instead_of_into.fixed @@ -1,16 +1,36 @@ // run-rustfix +#![allow(unused_imports)] #![warn(clippy::from_instead_of_into)] use std::convert::TryFrom; +use std::convert::TryInto; fn foo(a: T) where T: Into, { } + +fn foo1(a: T) +where T: Into, u32: Copy + Clone, +{ +} + fn bar(a: T) where T: TryInto, { } +fn bar1(a: T) +where + T: TryInto, u32: Copy + Clone, +{ +} + +fn bar2(a: T) +where + T: TryInto, u32: Copy + Clone, +{ +} + fn main() {} diff --git a/tests/ui/from_instead_of_into.rs b/tests/ui/from_instead_of_into.rs index 9e958951ebe2..0648e3032e91 100644 --- a/tests/ui/from_instead_of_into.rs +++ b/tests/ui/from_instead_of_into.rs @@ -2,6 +2,7 @@ #![allow(unused_imports)] #![warn(clippy::from_instead_of_into)] use std::convert::TryFrom; +use std::convert::TryInto; fn foo(a: T) where @@ -10,7 +11,8 @@ where } fn foo1(a: T) -where u32: Copy + Clone + From, +where + u32: Copy + Clone + From, { } @@ -26,4 +28,10 @@ where { } +fn bar2(a: T) +where + u32: TryFrom + Copy + Clone, +{ +} + fn main() {} diff --git a/tests/ui/from_instead_of_into.stderr b/tests/ui/from_instead_of_into.stderr index 39184b4931cc..59304c9f0ebc 100644 --- a/tests/ui/from_instead_of_into.stderr +++ b/tests/ui/from_instead_of_into.stderr @@ -1,16 +1,34 @@ error: Into trait is preferable than From as a generic bound - --> $DIR/from_instead_of_into.rs:7:5 + --> $DIR/from_instead_of_into.rs:9:5 | LL | u32: From, | ^^^^^^^^^^^^ help: try: `T: Into` | = note: `-D clippy::from-instead-of-into` implied by `-D warnings` +error: Into trait is preferable than From as a generic bound + --> $DIR/from_instead_of_into.rs:14:7 + | +LL | where u32: Copy + Clone + From, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: Into, u32: Copy + Clone` + error: TryInto trait is preferable than TryFrom as a generic bound - --> $DIR/from_instead_of_into.rs:12:5 + --> $DIR/from_instead_of_into.rs:20:5 | LL | u32: TryFrom, | ^^^^^^^^^^^^^^^ help: try: `T: TryInto` -error: aborting due to 2 previous errors +error: TryInto trait is preferable than TryFrom as a generic bound + --> $DIR/from_instead_of_into.rs:26:5 + | +LL | u32: Copy + TryFrom + Clone, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: TryInto, u32: Copy + Clone` + +error: TryInto trait is preferable than TryFrom as a generic bound + --> $DIR/from_instead_of_into.rs:32:5 + | +LL | u32: TryFrom + Copy + Clone, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: TryInto, u32: Copy + Clone` + +error: aborting due to 5 previous errors From 655520f0380d6602ad423189d9a91229492be6d4 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 19 Feb 2021 17:34:19 +0800 Subject: [PATCH 24/28] Satisfy with test. --- tests/ui/from_instead_of_into.fixed | 3 ++- tests/ui/from_instead_of_into.stderr | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/ui/from_instead_of_into.fixed b/tests/ui/from_instead_of_into.fixed index 62722f3685cc..6adbf8540193 100644 --- a/tests/ui/from_instead_of_into.fixed +++ b/tests/ui/from_instead_of_into.fixed @@ -11,7 +11,8 @@ where } fn foo1(a: T) -where T: Into, u32: Copy + Clone, +where + T: Into, u32: Copy + Clone, { } diff --git a/tests/ui/from_instead_of_into.stderr b/tests/ui/from_instead_of_into.stderr index 59304c9f0ebc..f3b39421567f 100644 --- a/tests/ui/from_instead_of_into.stderr +++ b/tests/ui/from_instead_of_into.stderr @@ -7,25 +7,25 @@ LL | u32: From, = note: `-D clippy::from-instead-of-into` implied by `-D warnings` error: Into trait is preferable than From as a generic bound - --> $DIR/from_instead_of_into.rs:14:7 + --> $DIR/from_instead_of_into.rs:15:5 | -LL | where u32: Copy + Clone + From, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: Into, u32: Copy + Clone` +LL | u32: Copy + Clone + From, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: Into, u32: Copy + Clone` error: TryInto trait is preferable than TryFrom as a generic bound - --> $DIR/from_instead_of_into.rs:20:5 + --> $DIR/from_instead_of_into.rs:21:5 | LL | u32: TryFrom, | ^^^^^^^^^^^^^^^ help: try: `T: TryInto` error: TryInto trait is preferable than TryFrom as a generic bound - --> $DIR/from_instead_of_into.rs:26:5 + --> $DIR/from_instead_of_into.rs:27:5 | LL | u32: Copy + TryFrom + Clone, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: TryInto, u32: Copy + Clone` error: TryInto trait is preferable than TryFrom as a generic bound - --> $DIR/from_instead_of_into.rs:32:5 + --> $DIR/from_instead_of_into.rs:33:5 | LL | u32: TryFrom + Copy + Clone, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: TryInto, u32: Copy + Clone` From 9eea1b6fa8e936388cca7bff3a7348e897db1fb8 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 19 Feb 2021 20:12:46 +0800 Subject: [PATCH 25/28] Refactor and update test. --- clippy_lints/src/from_instead_of_into.rs | 74 ++++++++++++++---------- tests/ui/from_instead_of_into.fixed | 2 + tests/ui/from_instead_of_into.rs | 2 + tests/ui/from_instead_of_into.stderr | 10 ++-- 4 files changed, 52 insertions(+), 36 deletions(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index dd3dc2a4c701..b6bd636d316b 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -6,6 +6,7 @@ use rustc_hir::*; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; +use std::borrow::Cow; declare_clippy_lint! { /// **What it does:** Checking for using of From or TryFrom trait as a generic bound. @@ -37,7 +38,7 @@ declare_lint_pass!(FromInsteadOfInto => [FROM_INSTEAD_OF_INTO]); impl LateLintPass<'tcx> for FromInsteadOfInto { fn check_where_predicate(&mut self, cx: &LateContext<'tcx>, wp: &'tcx WherePredicate<'tcx>) { - let is_target_generic_bound = |b: &GenericBound<'_>| { + fn is_target_generic_bound(cx: &LateContext<'tcx>, b: &GenericBound<'_>) -> bool { if_chain! { if let Some(r) = b.trait_ref(); if let Some(def_id) = r.trait_def_id(); @@ -48,12 +49,49 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { false } } - }; + } + + fn get_reduced_bounds_str( + cx: &LateContext<'tcx>, + position: usize, + bounds: GenericBounds<'tcx>, + ) -> Cow<'tcx, str> { + let before; + if position == 0 { + before = None; + } else { + let first_bound = &bounds[0]; + let previous_bound = &bounds[position - 1]; + before = Some(snippet( + cx, + first_bound.span().with_hi(previous_bound.span().hi()), + "..", + )); + } + + let after; + let last_position = bounds.len() - 1; + if position == last_position { + after = None; + } else { + let last_bound = &bounds[last_position]; + let after_bound = &bounds[position + 1]; + after = Some(snippet(cx, after_bound.span().with_hi(last_bound.span().hi()), "..")); + } + + match (before, after) { + (None, None) => unreachable!(), + (Some(b), None) => b, + (None, Some(a)) => a, + (Some(b), Some(a)) => b + " + " + a, + } + } + match wp { WherePredicate::BoundPredicate(wbp) => { if_chain! { let bounds = wbp.bounds; - if let Some(position) = bounds.iter().position(|b| is_target_generic_bound(b)); + if let Some(position) = bounds.iter().position(|b| is_target_generic_bound(cx, b)); let target_bound = &bounds[position]; if let Some(tr_ref) = target_bound.trait_ref(); if let Some(def_id) = tr_ref.trait_def_id(); @@ -61,7 +99,6 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { if let Some(generic_arg) = last_seg.args().args.first(); if let Some(bounded_ty) = snippet_opt(cx, wbp.bounded_ty.span); if let Some(generic_arg_of_from_or_try_from) = snippet_opt(cx, generic_arg.span()); - // if wbp.bounds.len() == 1; then { let replace_trait_name; let target_trait_name; @@ -84,33 +121,8 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { if bounds.len() == 1 { sugg = extracted_where_predicate; } else { - let before; - if position == 0 { - before = None; - } else { - let first_bound = &bounds[0]; - let previous_bound = &bounds[position-1]; - before = Some(snippet(cx, first_bound.span().with_hi(previous_bound.span().hi()), "..")); - } - - let after; - let last_position = bounds.len() - 1; - if position == last_position { - after = None; - } else { - let last_bound = &bounds[last_position]; - let after_bound = &bounds[position + 1]; - after = Some(snippet(cx, after_bound.span().with_hi(last_bound.span().hi()), "..")); - } - - let bounds_str = match (before, after) { - (None, None) => unreachable!(), - (Some(b), None) => b, - (None, Some(a)) => a, - (Some(b), Some(a)) => b + " + " + a, - }; - - sugg = format!("{}, {}: {}", extracted_where_predicate, bounded_ty, bounds_str); + let bounds = get_reduced_bounds_str(cx, position, bounds); + sugg = format!("{}, {}: {}", extracted_where_predicate, bounded_ty, bounds); } span_lint_and_sugg( cx, diff --git a/tests/ui/from_instead_of_into.fixed b/tests/ui/from_instead_of_into.fixed index 6adbf8540193..ff9ddb2d87d9 100644 --- a/tests/ui/from_instead_of_into.fixed +++ b/tests/ui/from_instead_of_into.fixed @@ -1,5 +1,7 @@ // run-rustfix #![allow(unused_imports)] +#![allow(unused_variables)] +#![allow(dead_code)] #![warn(clippy::from_instead_of_into)] use std::convert::TryFrom; use std::convert::TryInto; diff --git a/tests/ui/from_instead_of_into.rs b/tests/ui/from_instead_of_into.rs index 0648e3032e91..b56f4a10c164 100644 --- a/tests/ui/from_instead_of_into.rs +++ b/tests/ui/from_instead_of_into.rs @@ -1,5 +1,7 @@ // run-rustfix #![allow(unused_imports)] +#![allow(unused_variables)] +#![allow(dead_code)] #![warn(clippy::from_instead_of_into)] use std::convert::TryFrom; use std::convert::TryInto; diff --git a/tests/ui/from_instead_of_into.stderr b/tests/ui/from_instead_of_into.stderr index f3b39421567f..5bf718003852 100644 --- a/tests/ui/from_instead_of_into.stderr +++ b/tests/ui/from_instead_of_into.stderr @@ -1,5 +1,5 @@ error: Into trait is preferable than From as a generic bound - --> $DIR/from_instead_of_into.rs:9:5 + --> $DIR/from_instead_of_into.rs:11:5 | LL | u32: From, | ^^^^^^^^^^^^ help: try: `T: Into` @@ -7,25 +7,25 @@ LL | u32: From, = note: `-D clippy::from-instead-of-into` implied by `-D warnings` error: Into trait is preferable than From as a generic bound - --> $DIR/from_instead_of_into.rs:15:5 + --> $DIR/from_instead_of_into.rs:17:5 | LL | u32: Copy + Clone + From, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: Into, u32: Copy + Clone` error: TryInto trait is preferable than TryFrom as a generic bound - --> $DIR/from_instead_of_into.rs:21:5 + --> $DIR/from_instead_of_into.rs:23:5 | LL | u32: TryFrom, | ^^^^^^^^^^^^^^^ help: try: `T: TryInto` error: TryInto trait is preferable than TryFrom as a generic bound - --> $DIR/from_instead_of_into.rs:27:5 + --> $DIR/from_instead_of_into.rs:29:5 | LL | u32: Copy + TryFrom + Clone, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: TryInto, u32: Copy + Clone` error: TryInto trait is preferable than TryFrom as a generic bound - --> $DIR/from_instead_of_into.rs:33:5 + --> $DIR/from_instead_of_into.rs:35:5 | LL | u32: TryFrom + Copy + Clone, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: TryInto, u32: Copy + Clone` From ae2b38d886b0907ae6f65d625238e4d47842743b Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Fri, 19 Feb 2021 21:48:04 +0800 Subject: [PATCH 26/28] Fix workspace warning. --- clippy_lints/src/from_instead_of_into.rs | 93 ++++++++++++------------ 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index b6bd636d316b..4e8af8ff4d9d 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -2,7 +2,7 @@ use crate::utils::span_lint_and_sugg; use crate::utils::{snippet, snippet_opt}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::*; +use rustc_hir::{GenericBound, GenericBounds, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; @@ -87,57 +87,54 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { } } - match wp { - WherePredicate::BoundPredicate(wbp) => { - if_chain! { - let bounds = wbp.bounds; - if let Some(position) = bounds.iter().position(|b| is_target_generic_bound(cx, b)); - let target_bound = &bounds[position]; - if let Some(tr_ref) = target_bound.trait_ref(); - if let Some(def_id) = tr_ref.trait_def_id(); - if let Some(last_seg) = tr_ref.path.segments.last(); - if let Some(generic_arg) = last_seg.args().args.first(); - if let Some(bounded_ty) = snippet_opt(cx, wbp.bounded_ty.span); - if let Some(generic_arg_of_from_or_try_from) = snippet_opt(cx, generic_arg.span()); - then { - let replace_trait_name; - let target_trait_name; - if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { - replace_trait_name = "Into"; - target_trait_name = "From"; - } else if cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) { - replace_trait_name = "TryInto"; - target_trait_name = "TryFrom"; - } else { - replace_trait_name = ""; - target_trait_name = ""; - } + if let WherePredicate::BoundPredicate(wbp) = wp { + if_chain! { + let bounds = wbp.bounds; + if let Some(position) = bounds.iter().position(|b| is_target_generic_bound(cx, b)); + let target_bound = &bounds[position]; + if let Some(tr_ref) = target_bound.trait_ref(); + if let Some(def_id) = tr_ref.trait_def_id(); + if let Some(last_seg) = tr_ref.path.segments.last(); + if let Some(generic_arg) = last_seg.args().args.first(); + if let Some(bounded_ty) = snippet_opt(cx, wbp.bounded_ty.span); + if let Some(generic_arg_of_from_or_try_from) = snippet_opt(cx, generic_arg.span()); + then { + let replace_trait_name; + let target_trait_name; + if cx.tcx.is_diagnostic_item(sym::from_trait, def_id) { + replace_trait_name = "Into"; + target_trait_name = "From"; + } else if cx.tcx.is_diagnostic_item(sym::try_from_trait, def_id) { + replace_trait_name = "TryInto"; + target_trait_name = "TryFrom"; + } else { + replace_trait_name = ""; + target_trait_name = ""; + } - if !replace_trait_name.is_empty() && !target_trait_name.is_empty() { - let message = format!("{} trait is preferable than {} as a generic bound", replace_trait_name, target_trait_name); + if !replace_trait_name.is_empty() && !target_trait_name.is_empty() { + let message = format!("{} trait is preferable than {} as a generic bound", replace_trait_name, target_trait_name); - let extracted_where_predicate = format!("{}: {}<{}>", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); - let sugg; - if bounds.len() == 1 { - sugg = extracted_where_predicate; - } else { - let bounds = get_reduced_bounds_str(cx, position, bounds); - sugg = format!("{}, {}: {}", extracted_where_predicate, bounded_ty, bounds); - } - span_lint_and_sugg( - cx, - FROM_INSTEAD_OF_INTO, - wp.span(), - &message, - "try", - sugg, - Applicability::MaybeIncorrect - ); + let extracted_where_predicate = format!("{}: {}<{}>", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); + let sugg; + if bounds.len() == 1 { + sugg = extracted_where_predicate; + } else { + let bounds = get_reduced_bounds_str(cx, position, bounds); + sugg = format!("{}, {}: {}", extracted_where_predicate, bounded_ty, bounds); } + span_lint_and_sugg( + cx, + FROM_INSTEAD_OF_INTO, + wp.span(), + &message, + "try", + sugg, + Applicability::MaybeIncorrect + ); } } - }, - _ => (), - }; + } + } } } From 94232f324f37b842f6655a78864d2b545d92b504 Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Wed, 24 Feb 2021 01:39:56 +0800 Subject: [PATCH 27/28] Using span_lint_and_then method to lint. --- clippy_lints/src/from_instead_of_into.rs | 101 +++++++++-------------- 1 file changed, 40 insertions(+), 61 deletions(-) diff --git a/clippy_lints/src/from_instead_of_into.rs b/clippy_lints/src/from_instead_of_into.rs index 4e8af8ff4d9d..d690249ed7e2 100644 --- a/clippy_lints/src/from_instead_of_into.rs +++ b/clippy_lints/src/from_instead_of_into.rs @@ -1,12 +1,11 @@ -use crate::utils::span_lint_and_sugg; -use crate::utils::{snippet, snippet_opt}; +use crate::utils::span_lint_and_then; +use crate::utils::snippet_opt; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{GenericBound, GenericBounds, WherePredicate}; +use rustc_hir::{GenericBound, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::sym; -use std::borrow::Cow; declare_clippy_lint! { /// **What it does:** Checking for using of From or TryFrom trait as a generic bound. @@ -51,42 +50,6 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { } } - fn get_reduced_bounds_str( - cx: &LateContext<'tcx>, - position: usize, - bounds: GenericBounds<'tcx>, - ) -> Cow<'tcx, str> { - let before; - if position == 0 { - before = None; - } else { - let first_bound = &bounds[0]; - let previous_bound = &bounds[position - 1]; - before = Some(snippet( - cx, - first_bound.span().with_hi(previous_bound.span().hi()), - "..", - )); - } - - let after; - let last_position = bounds.len() - 1; - if position == last_position { - after = None; - } else { - let last_bound = &bounds[last_position]; - let after_bound = &bounds[position + 1]; - after = Some(snippet(cx, after_bound.span().with_hi(last_bound.span().hi()), "..")); - } - - match (before, after) { - (None, None) => unreachable!(), - (Some(b), None) => b, - (None, Some(a)) => a, - (Some(b), Some(a)) => b + " + " + a, - } - } - if let WherePredicate::BoundPredicate(wbp) = wp { if_chain! { let bounds = wbp.bounds; @@ -108,31 +71,47 @@ impl LateLintPass<'tcx> for FromInsteadOfInto { replace_trait_name = "TryInto"; target_trait_name = "TryFrom"; } else { - replace_trait_name = ""; - target_trait_name = ""; + return; } + let message = format!("{} trait is preferable than {} as a generic bound", replace_trait_name, target_trait_name); + let switched_predicate = format!("{}: {}<{}>", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); - if !replace_trait_name.is_empty() && !target_trait_name.is_empty() { - let message = format!("{} trait is preferable than {} as a generic bound", replace_trait_name, target_trait_name); + let low; + if position == 0 { + low = wp.span().lo(); + } else { + let previous_bound = &bounds[position -1]; + low = previous_bound.span().hi(); + } + let removed_span = target_bound.span().with_lo(low); - let extracted_where_predicate = format!("{}: {}<{}>", generic_arg_of_from_or_try_from, replace_trait_name, bounded_ty); - let sugg; - if bounds.len() == 1 { - sugg = extracted_where_predicate; - } else { - let bounds = get_reduced_bounds_str(cx, position, bounds); - sugg = format!("{}, {}: {}", extracted_where_predicate, bounded_ty, bounds); + span_lint_and_then( + cx, + FROM_INSTEAD_OF_INTO, + wp.span(), + &message, + |diag| { + diag.span_suggestion( + removed_span, + &format!("remove {} bound", target_trait_name), + "".to_string(), + Applicability::MaybeIncorrect, + ); + + let sugg; + if bounds.len() == 1 { + sugg = switched_predicate; + } else { + sugg = format!(", {}", switched_predicate); + } + diag.span_suggestion( + wp.span().with_lo(wp.span().hi()), + "Add this bound predicate", + sugg, + Applicability::MaybeIncorrect, + ); } - span_lint_and_sugg( - cx, - FROM_INSTEAD_OF_INTO, - wp.span(), - &message, - "try", - sugg, - Applicability::MaybeIncorrect - ); - } + ); } } } From 785d607fb4e3e17908f39827b636e16ea441bc9f Mon Sep 17 00:00:00 2001 From: xiongmao86 Date: Wed, 24 Feb 2021 16:09:38 +0800 Subject: [PATCH 28/28] Reference for pull request. --- tests/ui/from_instead_of_into.stderr | 54 +++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/tests/ui/from_instead_of_into.stderr b/tests/ui/from_instead_of_into.stderr index 5bf718003852..04a1acc88f35 100644 --- a/tests/ui/from_instead_of_into.stderr +++ b/tests/ui/from_instead_of_into.stderr @@ -2,33 +2,77 @@ error: Into trait is preferable than From as a generic bound --> $DIR/from_instead_of_into.rs:11:5 | LL | u32: From, - | ^^^^^^^^^^^^ help: try: `T: Into` + | ^^^^^^^^^^^^ | = note: `-D clippy::from-instead-of-into` implied by `-D warnings` +help: remove From bound + | +LL | , + | -- +help: Add this bound predicate + | +LL | u32: FromT: Into, + | ^^^^^^^^^^^^ error: Into trait is preferable than From as a generic bound --> $DIR/from_instead_of_into.rs:17:5 | LL | u32: Copy + Clone + From, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: Into, u32: Copy + Clone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove From bound + | +LL | u32: Copy + Clone, + | -- +help: Add this bound predicate + | +LL | u32: Copy + Clone + From, T: Into, + | ^^^^^^^^^^^^^^ error: TryInto trait is preferable than TryFrom as a generic bound --> $DIR/from_instead_of_into.rs:23:5 | LL | u32: TryFrom, - | ^^^^^^^^^^^^^^^ help: try: `T: TryInto` + | ^^^^^^^^^^^^^^^ + | +help: remove TryFrom bound + | +LL | , + | -- +help: Add this bound predicate + | +LL | u32: TryFromT: TryInto, + | ^^^^^^^^^^^^^^^ error: TryInto trait is preferable than TryFrom as a generic bound --> $DIR/from_instead_of_into.rs:29:5 | LL | u32: Copy + TryFrom + Clone, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: TryInto, u32: Copy + Clone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove TryFrom bound + | +LL | u32: Copy + Clone, + | -- +help: Add this bound predicate + | +LL | u32: Copy + TryFrom + Clone, T: TryInto, + | ^^^^^^^^^^^^^^^^^ error: TryInto trait is preferable than TryFrom as a generic bound --> $DIR/from_instead_of_into.rs:35:5 | LL | u32: TryFrom + Copy + Clone, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `T: TryInto, u32: Copy + Clone` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove TryFrom bound + | +LL | + Copy + Clone, + | -- +help: Add this bound predicate + | +LL | u32: TryFrom + Copy + Clone, T: TryInto, + | ^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors