about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-07-20 08:30:19 +0000
committerbors <bors@rust-lang.org>2023-07-20 08:30:19 +0000
commitfbe292e5634749db0712c14caf2de31955b1699f (patch)
tree7d50c69e8ff77ecb36f91127a333557d3d806050
parent0f31fff59ed0d2416043a291ab4c30a3d036648e (diff)
parent15b68c24b8bccbad6b3c9ec2e60a9540573365ce (diff)
downloadrust-fbe292e5634749db0712c14caf2de31955b1699f.tar.gz
rust-fbe292e5634749db0712c14caf2de31955b1699f.zip
Auto merge of #10971 - Centri3:unnecessary_cast_fully_qual_fix, r=dswij
Check for fully qualified paths in `unnecessary_cast`

Noticed this doesn't pick up `::std::primitive::u32` or the sort, now it does
changelog: none
-rw-r--r--clippy_lints/src/casts/mod.rs8
-rw-r--r--clippy_lints/src/casts/unnecessary_cast.rs22
-rw-r--r--tests/ui/unnecessary_cast.fixed17
-rw-r--r--tests/ui/unnecessary_cast.rs17
-rw-r--r--tests/ui/unnecessary_cast.stderr88
5 files changed, 104 insertions, 48 deletions
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index 0ac6ef6496a..d34de305f5d 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -181,6 +181,14 @@ declare_clippy_lint! {
     /// ### Why is this bad?
     /// It's just unnecessary.
     ///
+    /// ### Known problems
+    /// When the expression on the left is a function call, the lint considers the return type to be
+    /// a type alias if it's aliased through a `use` statement
+    /// (like `use std::io::Result as IoResult`). It will not lint such cases.
+    ///
+    /// This check is also rather primitive. It will only work on primitive types without any
+    /// intermediate references, raw pointers and trait objects may or may not work.
+    ///
     /// ### Example
     /// ```rust
     /// let _ = 2i32 as i32;
diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs
index 4b45b0c9eac..86057bb74ee 100644
--- a/clippy_lints/src/casts/unnecessary_cast.rs
+++ b/clippy_lints/src/casts/unnecessary_cast.rs
@@ -85,11 +85,6 @@ pub(super) fn check<'tcx>(
         }
     }
 
-    // skip cast of fn call that returns type alias
-    if let ExprKind::Cast(inner, ..) = expr.kind && is_cast_from_ty_alias(cx, inner, cast_from) {
-        return false;
-    }
-
     // skip cast to non-primitive type
     if_chain! {
         if let ExprKind::Cast(_, cast_to) = expr.kind;
@@ -101,6 +96,11 @@ pub(super) fn check<'tcx>(
         }
     }
 
+    // skip cast of fn call that returns type alias
+    if let ExprKind::Cast(inner, ..) = expr.kind && is_cast_from_ty_alias(cx, inner, cast_from) {
+        return false;
+    }
+
     if let Some(lit) = get_numeric_literal(cast_expr) {
         let literal_str = &cast_str;
 
@@ -254,14 +254,12 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
                 // function's declaration snippet is exactly equal to the `Ty`. That way, we can
                 // see whether it's a type alias.
                 //
-                // Will this work for more complex types? Probably not!
+                // FIXME: This won't work if the type is given an alias through `use`, should we
+                // consider this a type alias as well?
                 if !snippet
                     .split("->")
                     .skip(1)
-                    .map(|s| {
-                        s.trim() == cast_from.to_string()
-                            || s.split("where").any(|ty| ty.trim() == cast_from.to_string())
-                    })
+                    .map(|s| snippet_eq_ty(s, cast_from) || s.split("where").any(|ty| snippet_eq_ty(ty, cast_from)))
                     .any(|a| a)
                 {
                     return ControlFlow::Break(());
@@ -288,3 +286,7 @@ fn is_cast_from_ty_alias<'tcx>(cx: &LateContext<'tcx>, expr: impl Visitable<'tcx
     })
     .is_some()
 }
+
+fn snippet_eq_ty(snippet: &str, ty: Ty<'_>) -> bool {
+    snippet.trim() == ty.to_string() || snippet.trim().contains(&format!("::{ty}"))
+}
diff --git a/tests/ui/unnecessary_cast.fixed b/tests/ui/unnecessary_cast.fixed
index 8efd44baf59..2bf02f13414 100644
--- a/tests/ui/unnecessary_cast.fixed
+++ b/tests/ui/unnecessary_cast.fixed
@@ -38,6 +38,16 @@ mod fake_libc {
     }
 }
 
+fn aaa() -> ::std::primitive::u32 {
+    0
+}
+
+use std::primitive::u32 as UnsignedThirtyTwoBitInteger;
+
+fn bbb() -> UnsignedThirtyTwoBitInteger {
+    0
+}
+
 #[rustfmt::skip]
 fn main() {
     // Test cast_unnecessary
@@ -105,6 +115,13 @@ fn main() {
     extern_fake_libc::getpid_SAFE_TRUTH() as i32;
     let pid = unsafe { fake_libc::getpid() };
     pid as i32;
+    aaa();
+    let x = aaa();
+    aaa();
+    // Will not lint currently.
+    bbb() as u32;
+    let x = bbb();
+    bbb() as u32;
 
     let i8_ptr: *const i8 = &1;
     let u8_ptr: *const u8 = &1;
diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs
index c7723ef51f9..25b6b0f9b07 100644
--- a/tests/ui/unnecessary_cast.rs
+++ b/tests/ui/unnecessary_cast.rs
@@ -38,6 +38,16 @@ mod fake_libc {
     }
 }
 
+fn aaa() -> ::std::primitive::u32 {
+    0
+}
+
+use std::primitive::u32 as UnsignedThirtyTwoBitInteger;
+
+fn bbb() -> UnsignedThirtyTwoBitInteger {
+    0
+}
+
 #[rustfmt::skip]
 fn main() {
     // Test cast_unnecessary
@@ -105,6 +115,13 @@ fn main() {
     extern_fake_libc::getpid_SAFE_TRUTH() as i32;
     let pid = unsafe { fake_libc::getpid() };
     pid as i32;
+    aaa() as u32;
+    let x = aaa();
+    aaa() as u32;
+    // Will not lint currently.
+    bbb() as u32;
+    let x = bbb();
+    bbb() as u32;
 
     let i8_ptr: *const i8 = &1;
     let u8_ptr: *const u8 = &1;
diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr
index f0443556fb4..19411a01b67 100644
--- a/tests/ui/unnecessary_cast.stderr
+++ b/tests/ui/unnecessary_cast.stderr
@@ -7,226 +7,238 @@ LL |     ptr as *const T
    = note: `-D clippy::unnecessary-cast` implied by `-D warnings`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:44:5
+  --> $DIR/unnecessary_cast.rs:54:5
    |
 LL |     1i32 as i32;
    |     ^^^^^^^^^^^ help: try: `1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:45:5
+  --> $DIR/unnecessary_cast.rs:55:5
    |
 LL |     1f32 as f32;
    |     ^^^^^^^^^^^ help: try: `1_f32`
 
 error: casting to the same type is unnecessary (`bool` -> `bool`)
-  --> $DIR/unnecessary_cast.rs:46:5
+  --> $DIR/unnecessary_cast.rs:56:5
    |
 LL |     false as bool;
    |     ^^^^^^^^^^^^^ help: try: `false`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:49:5
+  --> $DIR/unnecessary_cast.rs:59:5
    |
 LL |     -1_i32 as i32;
    |     ^^^^^^^^^^^^^ help: try: `-1_i32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:50:5
+  --> $DIR/unnecessary_cast.rs:60:5
    |
 LL |     - 1_i32 as i32;
    |     ^^^^^^^^^^^^^^ help: try: `- 1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:51:5
+  --> $DIR/unnecessary_cast.rs:61:5
    |
 LL |     -1f32 as f32;
    |     ^^^^^^^^^^^^ help: try: `-1_f32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:52:5
+  --> $DIR/unnecessary_cast.rs:62:5
    |
 LL |     1_i32 as i32;
    |     ^^^^^^^^^^^^ help: try: `1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:53:5
+  --> $DIR/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`)
-  --> $DIR/unnecessary_cast.rs:55:22
+  --> $DIR/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`)
-  --> $DIR/unnecessary_cast.rs:57:5
+  --> $DIR/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`)
-  --> $DIR/unnecessary_cast.rs:59:5
+  --> $DIR/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`)
-  --> $DIR/unnecessary_cast.rs:70:5
+  --> $DIR/unnecessary_cast.rs:80:5
    |
 LL |     owo::<u32>([1u32].as_ptr()) as *const u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `owo::<u32>([1u32].as_ptr())`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*const u8` -> `*const u8`)
-  --> $DIR/unnecessary_cast.rs:71:5
+  --> $DIR/unnecessary_cast.rs:81:5
    |
 LL |     uwu::<u32, u8>([1u32].as_ptr()) as *const u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::<u32, u8>([1u32].as_ptr())`
 
 error: casting raw pointers to the same type and constness is unnecessary (`*const u32` -> `*const u32`)
-  --> $DIR/unnecessary_cast.rs:73:5
+  --> $DIR/unnecessary_cast.rs:83:5
    |
 LL |     uwu::<u32, u32>([1u32].as_ptr()) as *const u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `uwu::<u32, u32>([1u32].as_ptr())`
 
+error: casting to the same type is unnecessary (`u32` -> `u32`)
+  --> $DIR/unnecessary_cast.rs:118:5
+   |
+LL |     aaa() as u32;
+   |     ^^^^^^^^^^^^ help: try: `aaa()`
+
+error: casting to the same type is unnecessary (`u32` -> `u32`)
+  --> $DIR/unnecessary_cast.rs:120:5
+   |
+LL |     aaa() as u32;
+   |     ^^^^^^^^^^^^ help: try: `aaa()`
+
 error: casting integer literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:139:9
+  --> $DIR/unnecessary_cast.rs:156:9
    |
 LL |         100 as f32;
    |         ^^^^^^^^^^ help: try: `100_f32`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:140:9
+  --> $DIR/unnecessary_cast.rs:157:9
    |
 LL |         100 as f64;
    |         ^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:141:9
+  --> $DIR/unnecessary_cast.rs:158:9
    |
 LL |         100_i32 as f64;
    |         ^^^^^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:142:17
+  --> $DIR/unnecessary_cast.rs:159:17
    |
 LL |         let _ = -100 as f32;
    |                 ^^^^^^^^^^^ help: try: `-100_f32`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:143:17
+  --> $DIR/unnecessary_cast.rs:160:17
    |
 LL |         let _ = -100 as f64;
    |                 ^^^^^^^^^^^ help: try: `-100_f64`
 
 error: casting integer literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:144:17
+  --> $DIR/unnecessary_cast.rs:161:17
    |
 LL |         let _ = -100_i32 as f64;
    |                 ^^^^^^^^^^^^^^^ help: try: `-100_f64`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:145:9
+  --> $DIR/unnecessary_cast.rs:162:9
    |
 LL |         100. as f32;
    |         ^^^^^^^^^^^ help: try: `100_f32`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:146:9
+  --> $DIR/unnecessary_cast.rs:163:9
    |
 LL |         100. as f64;
    |         ^^^^^^^^^^^ help: try: `100_f64`
 
 error: casting integer literal to `u32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:158:9
+  --> $DIR/unnecessary_cast.rs:175:9
    |
 LL |         1 as u32;
    |         ^^^^^^^^ help: try: `1_u32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:159:9
+  --> $DIR/unnecessary_cast.rs:176:9
    |
 LL |         0x10 as i32;
    |         ^^^^^^^^^^^ help: try: `0x10_i32`
 
 error: casting integer literal to `usize` is unnecessary
-  --> $DIR/unnecessary_cast.rs:160:9
+  --> $DIR/unnecessary_cast.rs:177:9
    |
 LL |         0b10 as usize;
    |         ^^^^^^^^^^^^^ help: try: `0b10_usize`
 
 error: casting integer literal to `u16` is unnecessary
-  --> $DIR/unnecessary_cast.rs:161:9
+  --> $DIR/unnecessary_cast.rs:178:9
    |
 LL |         0o73 as u16;
    |         ^^^^^^^^^^^ help: try: `0o73_u16`
 
 error: casting integer literal to `u32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:162:9
+  --> $DIR/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
-  --> $DIR/unnecessary_cast.rs:164:9
+  --> $DIR/unnecessary_cast.rs:181:9
    |
 LL |         1.0 as f64;
    |         ^^^^^^^^^^ help: try: `1.0_f64`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:165:9
+  --> $DIR/unnecessary_cast.rs:182:9
    |
 LL |         0.5 as f32;
    |         ^^^^^^^^^^ help: try: `0.5_f32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:169:17
+  --> $DIR/unnecessary_cast.rs:186:17
    |
 LL |         let _ = -1 as i32;
    |                 ^^^^^^^^^ help: try: `-1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:170:17
+  --> $DIR/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`)
-  --> $DIR/unnecessary_cast.rs:176:18
+  --> $DIR/unnecessary_cast.rs:193:18
    |
 LL |         let _ = &(x as i32);
    |                  ^^^^^^^^^^ help: try: `{ x }`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast.rs:182:22
+  --> $DIR/unnecessary_cast.rs:199:22
    |
 LL |         let _: i32 = -(1) as i32;
    |                      ^^^^^^^^^^^ help: try: `-1_i32`
 
 error: casting integer literal to `i64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:184:22
+  --> $DIR/unnecessary_cast.rs:201:22
    |
 LL |         let _: i64 = -(1) as i64;
    |                      ^^^^^^^^^^^ help: try: `-1_i64`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast.rs:191:22
+  --> $DIR/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
-  --> $DIR/unnecessary_cast.rs:193:23
+  --> $DIR/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`)
-  --> $DIR/unnecessary_cast.rs:201:20
+  --> $DIR/unnecessary_cast.rs:218:20
    |
 LL |         let _num = foo() as f32;
    |                    ^^^^^^^^^^^^ help: try: `foo()`
 
-error: aborting due to 38 previous errors
+error: aborting due to 40 previous errors