Add missing_transmute_annotation lint

This commit is contained in:
Guillaume Gomez 2024-02-07 22:01:18 +01:00
parent c9f24827b3
commit 79766577f2
4 changed files with 89 additions and 0 deletions

View File

@ -5426,6 +5426,7 @@ Released 2018-09-13
[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
[`missing_spin_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_spin_loop
[`missing_trait_methods`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_trait_methods
[`missing_transmute_annotations`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_transmute_annotations
[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
[`mixed_attributes_style`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_attributes_style
[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals

View File

@ -677,6 +677,7 @@
crate::trait_bounds::TYPE_REPETITION_IN_BOUNDS_INFO,
crate::transmute::CROSSPOINTER_TRANSMUTE_INFO,
crate::transmute::EAGER_TRANSMUTE_INFO,
crate::transmute::MISSING_TRANSMUTE_ANNOTATIONS_INFO,
crate::transmute::TRANSMUTES_EXPRESSIBLE_AS_PTR_CASTS_INFO,
crate::transmute::TRANSMUTE_BYTES_TO_STR_INFO,
crate::transmute::TRANSMUTE_FLOAT_TO_INT_INFO,

View File

@ -0,0 +1,53 @@
use rustc_errors::Applicability;
use rustc_hir::{GenericArg, HirId, 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;
pub(super) fn check<'tcx>(
cx: &LateContext<'tcx>,
path: &Path<'tcx>,
from_ty: Ty<'tcx>,
to_ty: Ty<'tcx>,
expr_hir_id: HirId,
) -> bool {
let last = path.segments.last().unwrap();
if in_external_macro(cx.tcx.sess, last.ident.span) {
// If it comes from a non-local macro, we ignore it.
return false;
}
let args = last.args;
let missing_generic = match args {
Some(args) if !args.args.is_empty() => args.args.iter().any(|arg| match arg {
GenericArg::Infer(_) => true,
GenericArg::Type(ty) => matches!(ty.kind, TyKind::Infer),
_ => false,
}),
_ => true,
};
if !missing_generic {
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
// ... which does have type annotations.
&& local.ty.is_some()
{
return false;
}
span_lint_and_sugg(
cx,
MISSING_TRANSMUTE_ANNOTATIONS,
last.ident.span.with_hi(path.span.hi()),
"transmute used without annotations",
"consider adding missing annotations",
format!("{}::<{from_ty}, {to_ty}>", last.ident.as_str()),
Applicability::MaybeIncorrect,
);
true
}

View File

@ -1,5 +1,6 @@
mod crosspointer_transmute;
mod eager_transmute;
mod missing_transmute_annotations;
mod transmute_float_to_int;
mod transmute_int_to_bool;
mod transmute_int_to_char;
@ -520,6 +521,37 @@
"eager evaluation of `transmute`"
}
declare_clippy_lint! {
/// ### What it does
/// Checks if transmute calls have all generics specified.
///
/// ### Why is this bad?
/// If not set, some unexpected output type could be retrieved instead of the expected one,
/// potentially leading to invalid code.
///
/// This is particularly dangerous in case a seemingly innocent/unrelated change can cause type
/// inference to start inferring a different type. E.g. the transmute is the tail expression of
/// an `if` branch, and a different branches type changes, causing the transmute to silently
/// have a different type, instead of a proper error.
///
/// ### Example
/// ```no_run
/// # unsafe {
/// let x: i32 = std::mem::transmute([1u16, 2u16]);
/// # }
/// ```
/// Use instead:
/// ```no_run
/// # unsafe {
/// let x = std::mem::transmute::<[u16; 2], i32>([1u16, 2u16]);
/// # }
/// ```
#[clippy::version = "1.77.0"]
pub MISSING_TRANSMUTE_ANNOTATIONS,
suspicious,
"warns if a transmute call doesn't have all generics specified"
}
pub struct Transmute {
msrv: Msrv,
}
@ -542,6 +574,7 @@ pub struct Transmute {
TRANSMUTING_NULL,
TRANSMUTE_NULL_TO_FN,
EAGER_TRANSMUTE,
MISSING_TRANSMUTE_ANNOTATIONS,
]);
impl Transmute {
#[must_use]
@ -579,6 +612,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
| transmuting_null::check(cx, e, arg, to_ty)
| transmute_null_to_fn::check(cx, e, arg, to_ty)
| transmute_ptr_to_ref::check(cx, e, from_ty, to_ty, arg, path, &self.msrv)
| missing_transmute_annotations::check(cx, path, from_ty, to_ty, e.hir_id)
| transmute_int_to_char::check(cx, e, from_ty, to_ty, arg, const_context)
| transmute_ref_to_ref::check(cx, e, from_ty, to_ty, arg, const_context)
| transmute_ptr_to_ptr::check(cx, e, from_ty, to_ty, arg)