From d654acd554b679a61d9bde0247aa3ac8e691b964 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 10 Feb 2024 15:04:50 +0100 Subject: [PATCH 1/3] Add new `multiple_bound_locations` lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + clippy_lints/src/multiple_bound_locations.rs | 84 ++++++++++++++++++++ 4 files changed, 88 insertions(+) create mode 100644 clippy_lints/src/multiple_bound_locations.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index b35475c7340eb..d2afaa6ff9ef9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5430,6 +5430,7 @@ Released 2018-09-13 [`modulo_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_arithmetic [`modulo_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#modulo_one [`multi_assignments`]: https://rust-lang.github.io/rust-clippy/master/index.html#multi_assignments +[`multiple_bound_locations`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_bound_locations [`multiple_crate_versions`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_crate_versions [`multiple_inherent_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_inherent_impl [`multiple_unsafe_ops_per_block`]: https://rust-lang.github.io/rust-clippy/master/index.html#multiple_unsafe_ops_per_block diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 60744fee34d25..455bf990721a4 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -498,6 +498,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::module_style::MOD_MODULE_FILES_INFO, crate::module_style::SELF_NAMED_MODULE_FILES_INFO, crate::multi_assignments::MULTI_ASSIGNMENTS_INFO, + crate::multiple_bound_locations::MULTIPLE_BOUND_LOCATIONS_INFO, crate::multiple_unsafe_ops_per_block::MULTIPLE_UNSAFE_OPS_PER_BLOCK_INFO, crate::mut_key::MUTABLE_KEY_TYPE_INFO, crate::mut_mut::MUT_MUT_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 5636f46b22fee..99bae807e2c54 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -226,6 +226,7 @@ mod missing_trait_methods; mod mixed_read_write_in_expression; mod module_style; mod multi_assignments; +mod multiple_bound_locations; mod multiple_unsafe_ops_per_block; mod mut_key; mod mut_mut; @@ -1111,6 +1112,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { }); store.register_late_pass(move |_| Box::new(incompatible_msrv::IncompatibleMsrv::new(msrv()))); store.register_late_pass(|_| Box::new(to_string_trait_impl::ToStringTraitImpl)); + store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/multiple_bound_locations.rs b/clippy_lints/src/multiple_bound_locations.rs new file mode 100644 index 0000000000000..191b32408efe1 --- /dev/null +++ b/clippy_lints/src/multiple_bound_locations.rs @@ -0,0 +1,84 @@ +use rustc_ast::visit::FnKind; +use rustc_ast::{NodeId, WherePredicate}; +use rustc_data_structures::fx::FxHashMap; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::declare_lint_pass; +use rustc_span::Span; + +use clippy_utils::diagnostics::span_lint; +use clippy_utils::source::snippet_opt; + +declare_clippy_lint! { + /// ### What it does + /// Check if a generic is defined both in the bound predicate and in the `where` clause. + /// + /// ### Why is this bad? + /// It can be confusing for developers when seeing bounds for a generic in multiple places. + /// + /// ### Example + /// ```no_run + /// fn ty(a: F) + /// where + /// F: Sized, + /// {} + /// ``` + /// Use instead: + /// ```no_run + /// fn ty(a: F) + /// where + /// F: Sized + std::fmt::Debug, + /// {} + /// ``` + #[clippy::version = "1.77.0"] + pub MULTIPLE_BOUND_LOCATIONS, + suspicious, + "defining generic bounds in multiple locations" +} + +declare_lint_pass!(MultipleBoundLocations => [MULTIPLE_BOUND_LOCATIONS]); + +impl EarlyLintPass for MultipleBoundLocations { + fn check_fn(&mut self, cx: &EarlyContext<'_>, kind: FnKind<'_>, _: Span, _: NodeId) { + if let FnKind::Fn(_, _, _, _, generics, _) = kind + && !generics.params.is_empty() + && !generics.where_clause.predicates.is_empty() + { + let mut generic_params_with_bounds = FxHashMap::default(); + + for param in &generics.params { + if !param.bounds.is_empty() { + generic_params_with_bounds.insert(param.ident.name.as_str(), param.ident.span); + } + } + for clause in &generics.where_clause.predicates { + match clause { + WherePredicate::BoundPredicate(pred) => { + if (!pred.bound_generic_params.is_empty() || !pred.bounds.is_empty()) + && let Some(name) = snippet_opt(cx, pred.bounded_ty.span) + && let Some(bound_span) = generic_params_with_bounds.get(name.as_str()) + { + emit_lint(cx, *bound_span, pred.bounded_ty.span); + } + }, + WherePredicate::RegionPredicate(pred) => { + if !pred.bounds.is_empty() + && let Some(bound_span) = generic_params_with_bounds.get(&pred.lifetime.ident.name.as_str()) + { + emit_lint(cx, *bound_span, pred.lifetime.ident.span); + } + }, + WherePredicate::EqPredicate(_) => {}, + } + } + } + } +} + +fn emit_lint(cx: &EarlyContext<'_>, bound_span: Span, where_span: Span) { + span_lint( + cx, + MULTIPLE_BOUND_LOCATIONS, + vec![bound_span, where_span], + "bound is defined in more than one place", + ); +} From 6955a8ac4e861f51303aa57af310dc71dd842720 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 10 Feb 2024 15:05:11 +0100 Subject: [PATCH 2/3] Add ui test for `multiple_bound_locations` lint --- tests/ui/multiple_bound_locations.rs | 59 ++++++++++++++++++++++++ tests/ui/multiple_bound_locations.stderr | 59 ++++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 tests/ui/multiple_bound_locations.rs create mode 100644 tests/ui/multiple_bound_locations.stderr diff --git a/tests/ui/multiple_bound_locations.rs b/tests/ui/multiple_bound_locations.rs new file mode 100644 index 0000000000000..9f03db2c80146 --- /dev/null +++ b/tests/ui/multiple_bound_locations.rs @@ -0,0 +1,59 @@ +#![warn(clippy::multiple_bound_locations)] + +fn ty(a: F) +//~^ ERROR: bound is defined in more than one place +where + F: Sized, +{ +} + +fn lifetime<'a, 'b: 'a, 'c>(a: &'b str, b: &'a str, c: &'c str) +//~^ ERROR: bound is defined in more than one place +where + 'b: 'c, +{ +} + +fn ty_pred() +//~^ ERROR: bound is defined in more than one place +where + for<'a> F: Send + 'a, +{ +} + +struct B; + +impl B { + fn ty(a: F) + //~^ ERROR: bound is defined in more than one place + where + F: Sized, + { + } + + fn lifetime<'a, 'b: 'a, 'c>(a: &'b str, b: &'a str, c: &'c str) + //~^ ERROR: bound is defined in more than one place + where + 'b: 'c, + { + } + + fn ty_pred() + //~^ ERROR: bound is defined in more than one place + where + for<'a> F: Send + 'a, + { + } +} + +struct C(F); + +impl C { + fn foo(_f: F) -> Self + where F: std::fmt::Display + { + todo!() + } +} + +fn main() {} diff --git a/tests/ui/multiple_bound_locations.stderr b/tests/ui/multiple_bound_locations.stderr new file mode 100644 index 0000000000000..22dd2e0a55249 --- /dev/null +++ b/tests/ui/multiple_bound_locations.stderr @@ -0,0 +1,59 @@ +error: bound is defined in more than one place + --> tests/ui/multiple_bound_locations.rs:3:7 + | +LL | fn ty(a: F) + | ^ +... +LL | F: Sized, + | ^ + | + = note: `-D clippy::multiple-bound-locations` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::multiple_bound_locations)]` + +error: bound is defined in more than one place + --> tests/ui/multiple_bound_locations.rs:10:17 + | +LL | fn lifetime<'a, 'b: 'a, 'c>(a: &'b str, b: &'a str, c: &'c str) + | ^^ +... +LL | 'b: 'c, + | ^^ + +error: bound is defined in more than one place + --> tests/ui/multiple_bound_locations.rs:17:12 + | +LL | fn ty_pred() + | ^ +... +LL | for<'a> F: Send + 'a, + | ^ + +error: bound is defined in more than one place + --> tests/ui/multiple_bound_locations.rs:27:11 + | +LL | fn ty(a: F) + | ^ +... +LL | F: Sized, + | ^ + +error: bound is defined in more than one place + --> tests/ui/multiple_bound_locations.rs:34:21 + | +LL | fn lifetime<'a, 'b: 'a, 'c>(a: &'b str, b: &'a str, c: &'c str) + | ^^ +... +LL | 'b: 'c, + | ^^ + +error: bound is defined in more than one place + --> tests/ui/multiple_bound_locations.rs:41:16 + | +LL | fn ty_pred() + | ^ +... +LL | for<'a> F: Send + 'a, + | ^ + +error: aborting due to 6 previous errors + From 762448bc55f034aba15a62245b24a5fcd48166b9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 10 Feb 2024 15:09:12 +0100 Subject: [PATCH 3/3] Update ui tests --- tests/ui/multiple_bound_locations.rs | 5 +- .../trait_duplication_in_bounds_unfixable.rs | 1 + ...ait_duplication_in_bounds_unfixable.stderr | 16 ++-- tests/ui/type_repetition_in_bounds.rs | 2 +- tests/ui/unnecessary_cast.fixed | 1 + tests/ui/unnecessary_cast.rs | 1 + tests/ui/unnecessary_cast.stderr | 80 +++++++++---------- 7 files changed, 55 insertions(+), 51 deletions(-) diff --git a/tests/ui/multiple_bound_locations.rs b/tests/ui/multiple_bound_locations.rs index 9f03db2c80146..de9d994782ece 100644 --- a/tests/ui/multiple_bound_locations.rs +++ b/tests/ui/multiple_bound_locations.rs @@ -50,9 +50,10 @@ struct C(F); impl C { fn foo(_f: F) -> Self - where F: std::fmt::Display + where + F: std::fmt::Display, { - todo!() + todo!() } } diff --git a/tests/ui/trait_duplication_in_bounds_unfixable.rs b/tests/ui/trait_duplication_in_bounds_unfixable.rs index effed3a26938b..b0095bb77b5a0 100644 --- a/tests/ui/trait_duplication_in_bounds_unfixable.rs +++ b/tests/ui/trait_duplication_in_bounds_unfixable.rs @@ -1,4 +1,5 @@ #![deny(clippy::trait_duplication_in_bounds)] +#![allow(clippy::multiple_bound_locations)] use std::collections::BTreeMap; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; diff --git a/tests/ui/trait_duplication_in_bounds_unfixable.stderr b/tests/ui/trait_duplication_in_bounds_unfixable.stderr index 1d87e50e8a56c..41029007a98ee 100644 --- a/tests/ui/trait_duplication_in_bounds_unfixable.stderr +++ b/tests/ui/trait_duplication_in_bounds_unfixable.stderr @@ -1,5 +1,5 @@ error: this trait bound is already specified in the where clause - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:6:15 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:7:15 | LL | fn bad_foo(arg0: T, arg1: Z) | ^^^^^ @@ -12,7 +12,7 @@ LL | #![deny(clippy::trait_duplication_in_bounds)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this trait bound is already specified in the where clause - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:6:23 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:7:23 | LL | fn bad_foo(arg0: T, arg1: Z) | ^^^^^^^ @@ -20,7 +20,7 @@ LL | fn bad_foo(arg0: T, arg1: Z) = help: consider removing this trait bound error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:37:15 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:38:15 | LL | Self: Default; | ^^^^^^^ @@ -28,7 +28,7 @@ LL | Self: Default; = help: consider removing this trait bound error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:52:15 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:53:15 | LL | Self: Default + Clone; | ^^^^^^^ @@ -36,7 +36,7 @@ LL | Self: Default + Clone; = help: consider removing this trait bound error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:59:15 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:60:15 | LL | Self: Default + Clone; | ^^^^^^^ @@ -44,7 +44,7 @@ LL | Self: Default + Clone; = help: consider removing this trait bound error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:59:25 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:60:25 | LL | Self: Default + Clone; | ^^^^^ @@ -52,7 +52,7 @@ LL | Self: Default + Clone; = help: consider removing this trait bound error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:64:15 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:65:15 | LL | Self: Default; | ^^^^^^^ @@ -60,7 +60,7 @@ LL | Self: Default; = help: consider removing this trait bound error: this trait bound is already specified in trait declaration - --> tests/ui/trait_duplication_in_bounds_unfixable.rs:100:15 + --> tests/ui/trait_duplication_in_bounds_unfixable.rs:101:15 | LL | Self: Iterator, | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs index 504a003940502..0039c805b7df8 100644 --- a/tests/ui/type_repetition_in_bounds.rs +++ b/tests/ui/type_repetition_in_bounds.rs @@ -1,5 +1,5 @@ #![deny(clippy::type_repetition_in_bounds)] -#![allow(clippy::extra_unused_type_parameters)] +#![allow(clippy::extra_unused_type_parameters, clippy::multiple_bound_locations)] use serde::Deserialize; use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed index 18dd53bf2b42c..f52d325033987 100644 --- a/tests/ui/unnecessary_cast.fixed +++ b/tests/ui/unnecessary_cast.fixed @@ -2,6 +2,7 @@ #![warn(clippy::unnecessary_cast)] #![allow( clippy::borrow_as_ptr, + clippy::multiple_bound_locations, clippy::no_effect, clippy::nonstandard_macro_braces, clippy::unnecessary_operation, diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs index fcdd4c60ccd01..dfd8b454e6cca 100644 --- a/tests/ui/unnecessary_cast.rs +++ b/tests/ui/unnecessary_cast.rs @@ -2,6 +2,7 @@ #![warn(clippy::unnecessary_cast)] #![allow( clippy::borrow_as_ptr, + clippy::multiple_bound_locations, clippy::no_effect, clippy::nonstandard_macro_braces, clippy::unnecessary_operation, diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr index 9456c5acde39f..935bb71da32bd 100644 --- a/tests/ui/unnecessary_cast.stderr +++ b/tests/ui/unnecessary_cast.stderr @@ -1,5 +1,5 @@ error: casting raw pointers to the same type and constness is unnecessary (`*const T` -> `*const T`) - --> tests/ui/unnecessary_cast.rs:18:5 + --> tests/ui/unnecessary_cast.rs:19:5 | LL | ptr as *const T | ^^^^^^^^^^^^^^^ help: try: `ptr` @@ -8,235 +8,235 @@ LL | ptr as *const T = help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:53:5 + --> tests/ui/unnecessary_cast.rs:54:5 | LL | 1i32 as i32; | ^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:54:5 + --> tests/ui/unnecessary_cast.rs:55:5 | LL | 1f32 as f32; | ^^^^^^^^^^^ help: try: `1_f32` error: casting to the same type is unnecessary (`bool` -> `bool`) - --> tests/ui/unnecessary_cast.rs:55:5 + --> tests/ui/unnecessary_cast.rs:56:5 | LL | false as bool; | ^^^^^^^^^^^^^ help: try: `false` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:58:5 + --> tests/ui/unnecessary_cast.rs:59:5 | LL | -1_i32 as i32; | ^^^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:59:5 + --> tests/ui/unnecessary_cast.rs:60:5 | LL | - 1_i32 as i32; | ^^^^^^^^^^^^^^ help: try: `- 1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:60:5 + --> tests/ui/unnecessary_cast.rs:61:5 | LL | -1f32 as f32; | ^^^^^^^^^^^^ help: try: `-1_f32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:61:5 + --> tests/ui/unnecessary_cast.rs:62:5 | LL | 1_i32 as i32; | ^^^^^^^^^^^^ help: try: `1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:62:5 + --> tests/ui/unnecessary_cast.rs:63:5 | LL | 1_f32 as f32; | ^^^^^^^^^^^^ help: try: `1_f32` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> tests/ui/unnecessary_cast.rs:64:22 + --> tests/ui/unnecessary_cast.rs:65:22 | LL | let _: *mut u8 = [1u8, 2].as_ptr() as *const u8 as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> tests/ui/unnecessary_cast.rs:66:5 + --> tests/ui/unnecessary_cast.rs:67:5 | LL | [1u8, 2].as_ptr() as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*mut u8` -> `*mut u8`) - --> tests/ui/unnecessary_cast.rs:68:5 + --> tests/ui/unnecessary_cast.rs:69:5 | LL | [1u8, 2].as_mut_ptr() as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[1u8, 2].as_mut_ptr()` error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) - --> tests/ui/unnecessary_cast.rs:79:5 + --> tests/ui/unnecessary_cast.rs:80:5 | LL | owo::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::([1u32].as_ptr())` error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`) - --> tests/ui/unnecessary_cast.rs:80:5 + --> tests/ui/unnecessary_cast.rs:81:5 | LL | uwu::([1u32].as_ptr()) as *const u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`) - --> tests/ui/unnecessary_cast.rs:82:5 + --> tests/ui/unnecessary_cast.rs:83:5 | LL | uwu::([1u32].as_ptr()) as *const u32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::([1u32].as_ptr())` error: casting to the same type is unnecessary (`u32` -> `u32`) - --> tests/ui/unnecessary_cast.rs:117:5 + --> tests/ui/unnecessary_cast.rs:118:5 | LL | aaa() as u32; | ^^^^^^^^^^^^ help: try: `aaa()` error: casting to the same type is unnecessary (`u32` -> `u32`) - --> tests/ui/unnecessary_cast.rs:119:5 + --> tests/ui/unnecessary_cast.rs:120:5 | LL | aaa() as u32; | ^^^^^^^^^^^^ help: try: `aaa()` error: casting integer literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:155:9 + --> tests/ui/unnecessary_cast.rs:156:9 | LL | 100 as f32; | ^^^^^^^^^^ help: try: `100_f32` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:156:9 + --> tests/ui/unnecessary_cast.rs:157:9 | LL | 100 as f64; | ^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:157:9 + --> tests/ui/unnecessary_cast.rs:158:9 | LL | 100_i32 as f64; | ^^^^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:158:17 + --> tests/ui/unnecessary_cast.rs:159:17 | LL | let _ = -100 as f32; | ^^^^^^^^^^^ help: try: `-100_f32` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:159:17 + --> tests/ui/unnecessary_cast.rs:160:17 | LL | let _ = -100 as f64; | ^^^^^^^^^^^ help: try: `-100_f64` error: casting integer literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:160:17 + --> tests/ui/unnecessary_cast.rs:161:17 | LL | let _ = -100_i32 as f64; | ^^^^^^^^^^^^^^^ help: try: `-100_f64` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:161:9 + --> tests/ui/unnecessary_cast.rs:162:9 | LL | 100. as f32; | ^^^^^^^^^^^ help: try: `100_f32` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:162:9 + --> tests/ui/unnecessary_cast.rs:163:9 | LL | 100. as f64; | ^^^^^^^^^^^ help: try: `100_f64` error: casting integer literal to `u32` is unnecessary - --> tests/ui/unnecessary_cast.rs:174:9 + --> tests/ui/unnecessary_cast.rs:175:9 | LL | 1 as u32; | ^^^^^^^^ help: try: `1_u32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:175:9 + --> tests/ui/unnecessary_cast.rs:176:9 | LL | 0x10 as i32; | ^^^^^^^^^^^ help: try: `0x10_i32` error: casting integer literal to `usize` is unnecessary - --> tests/ui/unnecessary_cast.rs:176:9 + --> tests/ui/unnecessary_cast.rs:177:9 | LL | 0b10 as usize; | ^^^^^^^^^^^^^ help: try: `0b10_usize` error: casting integer literal to `u16` is unnecessary - --> tests/ui/unnecessary_cast.rs:177:9 + --> tests/ui/unnecessary_cast.rs:178:9 | LL | 0o73 as u16; | ^^^^^^^^^^^ help: try: `0o73_u16` error: casting integer literal to `u32` is unnecessary - --> tests/ui/unnecessary_cast.rs:178:9 + --> tests/ui/unnecessary_cast.rs:179:9 | LL | 1_000_000_000 as u32; | ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:180:9 + --> tests/ui/unnecessary_cast.rs:181:9 | LL | 1.0 as f64; | ^^^^^^^^^^ help: try: `1.0_f64` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:181:9 + --> tests/ui/unnecessary_cast.rs:182:9 | LL | 0.5 as f32; | ^^^^^^^^^^ help: try: `0.5_f32` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:185:17 + --> tests/ui/unnecessary_cast.rs:186:17 | LL | let _ = -1 as i32; | ^^^^^^^^^ help: try: `-1_i32` error: casting float literal to `f32` is unnecessary - --> tests/ui/unnecessary_cast.rs:186:17 + --> tests/ui/unnecessary_cast.rs:187:17 | LL | let _ = -1.0 as f32; | ^^^^^^^^^^^ help: try: `-1.0_f32` error: casting to the same type is unnecessary (`i32` -> `i32`) - --> tests/ui/unnecessary_cast.rs:192:18 + --> tests/ui/unnecessary_cast.rs:193:18 | LL | let _ = &(x as i32); | ^^^^^^^^^^ help: try: `{ x }` error: casting integer literal to `i32` is unnecessary - --> tests/ui/unnecessary_cast.rs:198:22 + --> tests/ui/unnecessary_cast.rs:199:22 | LL | let _: i32 = -(1) as i32; | ^^^^^^^^^^^ help: try: `-1_i32` error: casting integer literal to `i64` is unnecessary - --> tests/ui/unnecessary_cast.rs:200:22 + --> tests/ui/unnecessary_cast.rs:201:22 | LL | let _: i64 = -(1) as i64; | ^^^^^^^^^^^ help: try: `-1_i64` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:207:22 + --> tests/ui/unnecessary_cast.rs:208:22 | LL | let _: f64 = (-8.0 as f64).exp(); | ^^^^^^^^^^^^^ help: try: `(-8.0_f64)` error: casting float literal to `f64` is unnecessary - --> tests/ui/unnecessary_cast.rs:209:23 + --> tests/ui/unnecessary_cast.rs:210:23 | LL | let _: f64 = -(8.0 as f64).exp(); // should suggest `-8.0_f64.exp()` here not to change code behavior | ^^^^^^^^^^^^ help: try: `8.0_f64` error: casting to the same type is unnecessary (`f32` -> `f32`) - --> tests/ui/unnecessary_cast.rs:217:20 + --> tests/ui/unnecessary_cast.rs:218:20 | LL | let _num = foo() as f32; | ^^^^^^^^^^^^ help: try: `foo()`