about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-03-15 18:42:35 +0100
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2024-03-24 00:50:28 +0100
commitee2558223f51b894475dcd1458b21f7ea393508a (patch)
treed337e869113574909b7542ad737fdbb2bceea134
parentffa12798c0f24fb2fe8659aa917a9b9308f8bc7b (diff)
downloadrust-ee2558223f51b894475dcd1458b21f7ea393508a.tar.gz
rust-ee2558223f51b894475dcd1458b21f7ea393508a.zip
Do no emit `missing_transmute_annotations` lint if the `transmute` is the only expr in the function
-rw-r--r--clippy_lints/src/transmute/missing_transmute_annotations.rs25
-rw-r--r--tests/ui/missing_transmute_annotations.fixed56
-rw-r--r--tests/ui/missing_transmute_annotations.rs54
-rw-r--r--tests/ui/missing_transmute_annotations.stderr50
4 files changed, 90 insertions, 95 deletions
diff --git a/clippy_lints/src/transmute/missing_transmute_annotations.rs b/clippy_lints/src/transmute/missing_transmute_annotations.rs
index 84f3d9c169a..ec7041b945b 100644
--- a/clippy_lints/src/transmute/missing_transmute_annotations.rs
+++ b/clippy_lints/src/transmute/missing_transmute_annotations.rs
@@ -1,11 +1,10 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
 use rustc_errors::Applicability;
 use rustc_hir::{GenericArg, HirId, Local, Node, Path, TyKind};
 use rustc_lint::LateContext;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::Ty;
 
-use clippy_utils::diagnostics::span_lint_and_sugg;
-
 use crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS;
 
 fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId) -> Option<Local<'tcx>> {
@@ -29,6 +28,15 @@ fn get_parent_local_binding_ty<'tcx>(cx: &LateContext<'tcx>, expr_hir_id: HirId)
     }
 }
 
+fn is_function_block(cx: &LateContext<'_>, expr_hir_id: HirId) -> bool {
+    let def_id = cx.tcx.hir().enclosing_body_owner(expr_hir_id);
+    if let Some(body_id) = cx.tcx.hir().maybe_body_owned_by(def_id) {
+        let body = cx.tcx.hir().body(body_id);
+        return body.value.peel_blocks().hir_id == expr_hir_id;
+    }
+    false
+}
+
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
     path: &Path<'tcx>,
@@ -54,14 +62,17 @@ pub(super) fn check<'tcx>(
         return false;
     }
     // If it's being set as a local variable value...
-    if let Some(local) = get_parent_local_binding_ty(cx, expr_hir_id)
+    if let Some(local) = get_parent_local_binding_ty(cx, expr_hir_id) {
         // ... which does have type annotations.
-        && let Some(ty) = local.ty
-    {
-        // If this is a `let x: _ =`, we shouldn't lint.
-        if !matches!(ty.kind, TyKind::Infer) {
+        if let Some(ty) = local.ty
+            // If this is a `let x: _ =`, we should lint.
+            && !matches!(ty.kind, TyKind::Infer)
+        {
             return false;
         }
+    // We check if this transmute is not the only element in the function
+    } else if is_function_block(cx, expr_hir_id) {
+        return false;
     }
     span_lint_and_sugg(
         cx,
diff --git a/tests/ui/missing_transmute_annotations.fixed b/tests/ui/missing_transmute_annotations.fixed
index 7fe8063f40f..a3c94ab139e 100644
--- a/tests/ui/missing_transmute_annotations.fixed
+++ b/tests/ui/missing_transmute_annotations.fixed
@@ -9,6 +9,7 @@ extern crate macro_rules;
 macro_rules! local_bad_transmute {
     ($e:expr) => {
         std::mem::transmute::<[u16; 2], i32>($e)
+        //~^ ERROR: transmute used without annotations
     };
 }
 
@@ -17,55 +18,46 @@ fn bar(x: i32) -> i32 {
 }
 
 unsafe fn foo1() -> i32 {
-    std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])
-    //~^ ERROR: transmute used without annotations
+    // Should not warn!
+    std::mem::transmute([1u16, 2u16])
 }
 
-unsafe fn foo2() -> i32 {
-    std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])
-    //~^ ERROR: transmute used without annotations
-}
+// Should not warn!
+const _: i32 = unsafe { std::mem::transmute([1u16, 2u16]) };
 
-unsafe fn foo3() -> i32 {
-    std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])
-    //~^ ERROR: transmute used without annotations
+#[repr(i32)]
+enum Foo {
+    A = 0,
 }
 
-unsafe fn foo4() -> i32 {
-    std::mem::transmute::<[u16; 2], i32>([1u16, 2u16])
+unsafe fn foo2() -> i32 {
+    let mut i: i32 = 0;
+    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
     //~^ ERROR: transmute used without annotations
-}
 
-unsafe fn foo5() -> i32 {
     let x: i32 = bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]));
     //~^ ERROR: transmute used without annotations
-    bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]))
+    bar(std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]));
     //~^ ERROR: transmute used without annotations
-}
 
-unsafe fn foo6() -> i32 {
-    local_bad_transmute!([1u16, 2u16])
-    //~^ ERROR: transmute used without annotations
-}
+    i = local_bad_transmute!([1u16, 2u16]);
 
-unsafe fn foo7() -> i32 {
     // Should not warn.
-    bad_transmute!([1u16, 2u16])
-}
-
-#[repr(i32)]
-enum Foo {
-    A = 0,
-}
+    i = bad_transmute!([1u16, 2u16]);
 
-unsafe fn foo8() -> Foo {
-    std::mem::transmute::<i32, Foo>(0i32)
+    i = std::mem::transmute::<[i16; 2], i32>([0i16, 0i16]);
     //~^ ERROR: transmute used without annotations
-}
 
-unsafe fn foo9() -> i32 {
-    std::mem::transmute::<Foo, i32>(Foo::A)
+    i = std::mem::transmute::<Foo, i32>(Foo::A);
     //~^ ERROR: transmute used without annotations
+
+    i
 }
 
 fn main() {
diff --git a/tests/ui/missing_transmute_annotations.rs b/tests/ui/missing_transmute_annotations.rs
index 9c42077054e..c12e1b0f8d2 100644
--- a/tests/ui/missing_transmute_annotations.rs
+++ b/tests/ui/missing_transmute_annotations.rs
@@ -9,6 +9,7 @@ extern crate macro_rules;
 macro_rules! local_bad_transmute {
     ($e:expr) => {
         std::mem::transmute($e)
+        //~^ ERROR: transmute used without annotations
     };
 }
 
@@ -17,55 +18,46 @@ fn bar(x: i32) -> i32 {
 }
 
 unsafe fn foo1() -> i32 {
+    // Should not warn!
     std::mem::transmute([1u16, 2u16])
-    //~^ ERROR: transmute used without annotations
 }
 
-unsafe fn foo2() -> i32 {
-    std::mem::transmute::<_, _>([1u16, 2u16])
-    //~^ ERROR: transmute used without annotations
-}
+// Should not warn!
+const _: i32 = unsafe { std::mem::transmute([1u16, 2u16]) };
 
-unsafe fn foo3() -> i32 {
-    std::mem::transmute::<_, i32>([1u16, 2u16])
-    //~^ ERROR: transmute used without annotations
+#[repr(i32)]
+enum Foo {
+    A = 0,
 }
 
-unsafe fn foo4() -> i32 {
-    std::mem::transmute::<[u16; 2], _>([1u16, 2u16])
+unsafe fn foo2() -> i32 {
+    let mut i: i32 = 0;
+    i = std::mem::transmute([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<_, _>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<_, i32>([1u16, 2u16]);
+    //~^ ERROR: transmute used without annotations
+    i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
     //~^ ERROR: transmute used without annotations
-}
 
-unsafe fn foo5() -> i32 {
     let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
     //~^ ERROR: transmute used without annotations
-    bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]))
+    bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
     //~^ ERROR: transmute used without annotations
-}
 
-unsafe fn foo6() -> i32 {
-    local_bad_transmute!([1u16, 2u16])
-    //~^ ERROR: transmute used without annotations
-}
+    i = local_bad_transmute!([1u16, 2u16]);
 
-unsafe fn foo7() -> i32 {
     // Should not warn.
-    bad_transmute!([1u16, 2u16])
-}
-
-#[repr(i32)]
-enum Foo {
-    A = 0,
-}
+    i = bad_transmute!([1u16, 2u16]);
 
-unsafe fn foo8() -> Foo {
-    std::mem::transmute(0i32)
+    i = std::mem::transmute([0i16, 0i16]);
     //~^ ERROR: transmute used without annotations
-}
 
-unsafe fn foo9() -> i32 {
-    std::mem::transmute(Foo::A)
+    i = std::mem::transmute(Foo::A);
     //~^ ERROR: transmute used without annotations
+
+    i
 }
 
 fn main() {
diff --git a/tests/ui/missing_transmute_annotations.stderr b/tests/ui/missing_transmute_annotations.stderr
index 180cd007b13..5903ed488ef 100644
--- a/tests/ui/missing_transmute_annotations.stderr
+++ b/tests/ui/missing_transmute_annotations.stderr
@@ -1,40 +1,40 @@
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:20:15
+  --> tests/ui/missing_transmute_annotations.rs:35:19
    |
-LL |     std::mem::transmute([1u16, 2u16])
-   |               ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |     i = std::mem::transmute([1u16, 2u16]);
+   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
    |
    = note: `-D clippy::missing-transmute-annotations` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::missing_transmute_annotations)]`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:25:15
+  --> tests/ui/missing_transmute_annotations.rs:37:19
    |
-LL |     std::mem::transmute::<_, _>([1u16, 2u16])
-   |               ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |     i = std::mem::transmute::<_, _>([1u16, 2u16]);
+   |                   ^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:30:15
+  --> tests/ui/missing_transmute_annotations.rs:39:19
    |
-LL |     std::mem::transmute::<_, i32>([1u16, 2u16])
-   |               ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |     i = std::mem::transmute::<_, i32>([1u16, 2u16]);
+   |                   ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:35:15
+  --> tests/ui/missing_transmute_annotations.rs:41:19
    |
-LL |     std::mem::transmute::<[u16; 2], _>([1u16, 2u16])
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
+LL |     i = std::mem::transmute::<[u16; 2], _>([1u16, 2u16]);
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:40:32
+  --> tests/ui/missing_transmute_annotations.rs:44:32
    |
 LL |     let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:42:19
+  --> tests/ui/missing_transmute_annotations.rs:46:19
    |
-LL |     bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]))
+LL |     bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16]));
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
@@ -43,31 +43,31 @@ error: transmute used without annotations
 LL |         std::mem::transmute($e)
    |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 ...
-LL |     local_bad_transmute!([1u16, 2u16])
-   |     ---------------------------------- in this macro invocation
+LL |     i = local_bad_transmute!([1u16, 2u16]);
+   |         ---------------------------------- in this macro invocation
    |
    = note: this error originates in the macro `local_bad_transmute` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:62:15
+  --> tests/ui/missing_transmute_annotations.rs:54:19
    |
-LL |     std::mem::transmute(0i32)
-   |               ^^^^^^^^^ help: consider adding missing annotations: `transmute::<i32, Foo>`
+LL |     i = std::mem::transmute([0i16, 0i16]);
+   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[i16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:67:15
+  --> tests/ui/missing_transmute_annotations.rs:57:19
    |
-LL |     std::mem::transmute(Foo::A)
-   |               ^^^^^^^^^ help: consider adding missing annotations: `transmute::<Foo, i32>`
+LL |     i = std::mem::transmute(Foo::A);
+   |                   ^^^^^^^^^ help: consider adding missing annotations: `transmute::<Foo, i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:72:35
+  --> tests/ui/missing_transmute_annotations.rs:64:35
    |
 LL |     let x: _ = unsafe { std::mem::transmute::<_, i32>([1u16, 2u16]) };
    |                                   ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`
 
 error: transmute used without annotations
-  --> tests/ui/missing_transmute_annotations.rs:75:30
+  --> tests/ui/missing_transmute_annotations.rs:67:30
    |
 LL |         let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]);
    |                              ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>`