From ffa12798c0f24fb2fe8659aa917a9b9308f8bc7b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 25 Feb 2024 18:12:32 +0100 Subject: [PATCH] Correctly handle `transmute` as return value from `block` and `let var: _ = transmute` --- .../missing_transmute_annotations.rs | 33 ++++++++++++++++--- tests/ui/missing_transmute_annotations.fixed | 7 ++++ tests/ui/missing_transmute_annotations.rs | 7 ++++ tests/ui/missing_transmute_annotations.stderr | 32 ++++++++++++------ 4 files changed, 64 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/transmute/missing_transmute_annotations.rs b/clippy_lints/src/transmute/missing_transmute_annotations.rs index cbc52b6b8..84f3d9c16 100644 --- a/clippy_lints/src/transmute/missing_transmute_annotations.rs +++ b/clippy_lints/src/transmute/missing_transmute_annotations.rs @@ -1,5 +1,5 @@ use rustc_errors::Applicability; -use rustc_hir::{GenericArg, HirId, Node, Path, TyKind}; +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; @@ -8,6 +8,27 @@ 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> { + let mut parent_iter = cx.tcx.hir().parent_iter(expr_hir_id); + if let Some((_, node)) = parent_iter.next() { + match node { + Node::Local(local) => Some(*local), + Node::Block(_) => { + if let Some((parent_hir_id, Node::Expr(expr))) = parent_iter.next() + && matches!(expr.kind, rustc_hir::ExprKind::Block(_, _)) + { + get_parent_local_binding_ty(cx, parent_hir_id) + } else { + None + } + }, + _ => None, + } + } else { + None + } +} + pub(super) fn check<'tcx>( cx: &LateContext<'tcx>, path: &Path<'tcx>, @@ -33,12 +54,14 @@ pub(super) fn check<'tcx>( return false; } // If it's being set as a local variable value... - if let Some((_, node)) = cx.tcx.hir().parent_iter(expr_hir_id).next() - && let Node::Local(local) = node + if let Some(local) = get_parent_local_binding_ty(cx, expr_hir_id) // ... which does have type annotations. - && local.ty.is_some() + && let Some(ty) = local.ty { - return false; + // If this is a `let x: _ =`, we shouldn't lint. + if !matches!(ty.kind, TyKind::Infer) { + return false; + } } span_lint_and_sugg( cx, diff --git a/tests/ui/missing_transmute_annotations.fixed b/tests/ui/missing_transmute_annotations.fixed index cf6117b17..7fe8063f4 100644 --- a/tests/ui/missing_transmute_annotations.fixed +++ b/tests/ui/missing_transmute_annotations.fixed @@ -1,6 +1,7 @@ //@aux-build:macro_rules.rs #![warn(clippy::missing_transmute_annotations)] +#![allow(clippy::let_with_type_underscore)] #[macro_use] extern crate macro_rules; @@ -68,7 +69,12 @@ unsafe fn foo9() -> i32 { } fn main() { + let x: _ = unsafe { std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]) }; + //~^ ERROR: transmute used without annotations unsafe { + let x: _ = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + // Should not warn. std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); @@ -76,4 +82,5 @@ fn main() { let x: i32 = std::mem::transmute::<_, i32>([1u16, 2u16]); let x: i32 = std::mem::transmute([1u16, 2u16]); } + let x: i32 = unsafe { std::mem::transmute([1u16, 2u16]) }; } diff --git a/tests/ui/missing_transmute_annotations.rs b/tests/ui/missing_transmute_annotations.rs index 53fd7a849..9c4207705 100644 --- a/tests/ui/missing_transmute_annotations.rs +++ b/tests/ui/missing_transmute_annotations.rs @@ -1,6 +1,7 @@ //@aux-build:macro_rules.rs #![warn(clippy::missing_transmute_annotations)] +#![allow(clippy::let_with_type_underscore)] #[macro_use] extern crate macro_rules; @@ -68,7 +69,12 @@ unsafe fn foo9() -> i32 { } fn main() { + let x: _ = unsafe { std::mem::transmute::<_, i32>([1u16, 2u16]) }; + //~^ ERROR: transmute used without annotations unsafe { + let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]); + //~^ ERROR: transmute used without annotations + // Should not warn. std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]); @@ -76,4 +82,5 @@ fn main() { let x: i32 = std::mem::transmute::<_, i32>([1u16, 2u16]); let x: i32 = std::mem::transmute([1u16, 2u16]); } + let x: i32 = unsafe { std::mem::transmute([1u16, 2u16]) }; } diff --git a/tests/ui/missing_transmute_annotations.stderr b/tests/ui/missing_transmute_annotations.stderr index 9f2e8e8c9..180cd007b 100644 --- a/tests/ui/missing_transmute_annotations.stderr +++ b/tests/ui/missing_transmute_annotations.stderr @@ -1,5 +1,5 @@ error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:19:15 + --> tests/ui/missing_transmute_annotations.rs:20:15 | LL | std::mem::transmute([1u16, 2u16]) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` @@ -8,37 +8,37 @@ LL | std::mem::transmute([1u16, 2u16]) = help: to override `-D warnings` add `#[allow(clippy::missing_transmute_annotations)]` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:24:15 + --> tests/ui/missing_transmute_annotations.rs:25:15 | LL | 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:29:15 + --> tests/ui/missing_transmute_annotations.rs:30:15 | LL | 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:34:15 + --> tests/ui/missing_transmute_annotations.rs:35:15 | LL | 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:39:32 + --> tests/ui/missing_transmute_annotations.rs:40: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:41:19 + --> tests/ui/missing_transmute_annotations.rs:42:19 | LL | 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:10:19 + --> tests/ui/missing_transmute_annotations.rs:11:19 | LL | std::mem::transmute($e) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` @@ -49,16 +49,28 @@ LL | local_bad_transmute!([1u16, 2u16]) = 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:61:15 + --> tests/ui/missing_transmute_annotations.rs:62:15 | LL | std::mem::transmute(0i32) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` error: transmute used without annotations - --> tests/ui/missing_transmute_annotations.rs:66:15 + --> tests/ui/missing_transmute_annotations.rs:67:15 | LL | std::mem::transmute(Foo::A) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::` -error: aborting due to 9 previous errors +error: transmute used without annotations + --> tests/ui/missing_transmute_annotations.rs:72: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 + | +LL | let x: _ = std::mem::transmute::<_, i32>([1u16, 2u16]); + | ^^^^^^^^^^^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` + +error: aborting due to 11 previous errors