From ee2558223f51b894475dcd1458b21f7ea393508a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 15 Mar 2024 18:42:35 +0100 Subject: [PATCH] Do no emit `missing_transmute_annotations` lint if the `transmute` is the only expr in the function --- .../missing_transmute_annotations.rs | 25 +++++-- tests/ui/missing_transmute_annotations.fixed | 68 ++++++++----------- tests/ui/missing_transmute_annotations.rs | 66 ++++++++---------- tests/ui/missing_transmute_annotations.stderr | 50 +++++++------- 4 files changed, 102 insertions(+), 107 deletions(-) diff --git a/clippy_lints/src/transmute/missing_transmute_annotations.rs b/clippy_lints/src/transmute/missing_transmute_annotations.rs index 84f3d9c169a4..ec7041b945b3 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> { @@ -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 7fe8063f40f8..a3c94ab139ec 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 -} - -unsafe fn foo3() -> i32 { - std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo4() -> i32 { - 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])) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo6() -> i32 { - local_bad_transmute!([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo7() -> i32 { - // Should not warn. - bad_transmute!([1u16, 2u16]) -} +// Should not warn! +const _: i32 = unsafe { std::mem::transmute([1u16, 2u16]) }; #[repr(i32)] enum Foo { A = 0, } -unsafe fn foo8() -> Foo { - std::mem::transmute::(0i32) +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 foo9() -> i32 { - std::mem::transmute::(Foo::A) + 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])); + //~^ ERROR: transmute used without annotations + + i = local_bad_transmute!([1u16, 2u16]); + + // Should not warn. + i = bad_transmute!([1u16, 2u16]); + + i = std::mem::transmute::<[i16; 2], i32>([0i16, 0i16]); + //~^ ERROR: transmute used without annotations + + i = std::mem::transmute::(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 9c42077054ec..c12e1b0f8d22 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 -} - -unsafe fn foo3() -> i32 { - std::mem::transmute::<_, i32>([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo4() -> i32 { - 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])) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo6() -> i32 { - local_bad_transmute!([1u16, 2u16]) - //~^ ERROR: transmute used without annotations -} - -unsafe fn foo7() -> i32 { - // Should not warn. - bad_transmute!([1u16, 2u16]) -} +// Should not warn! +const _: i32 = unsafe { std::mem::transmute([1u16, 2u16]) }; #[repr(i32)] enum Foo { A = 0, } -unsafe fn foo8() -> Foo { - std::mem::transmute(0i32) +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 foo9() -> i32 { - std::mem::transmute(Foo::A) + let x: i32 = bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); //~^ ERROR: transmute used without annotations + bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); + //~^ ERROR: transmute used without annotations + + i = local_bad_transmute!([1u16, 2u16]); + + // Should not warn. + i = bad_transmute!([1u16, 2u16]); + + i = std::mem::transmute([0i16, 0i16]); + //~^ ERROR: transmute used without annotations + + 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 180cd007b135..5903ed488ef1 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::` +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::` +LL | i = std::mem::transmute(Foo::A); + | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` 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>`