mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-26 14:40:32 +00:00
Add missing_transmute_annotation
lint
This commit is contained in:
parent
c9f24827b3
commit
79766577f2
4 changed files with 89 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -677,6 +677,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
|
|||
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,
|
||||
|
|
53
clippy_lints/src/transmute/missing_transmute_annotations.rs
Normal file
53
clippy_lints/src/transmute/missing_transmute_annotations.rs
Normal 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
|
||||
}
|
|
@ -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 @@ declare_clippy_lint! {
|
|||
"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 @@ impl_lint_pass!(Transmute => [
|
|||
TRANSMUTING_NULL,
|
||||
TRANSMUTE_NULL_TO_FN,
|
||||
EAGER_TRANSMUTE,
|
||||
MISSING_TRANSMUTE_ANNOTATIONS,
|
||||
]);
|
||||
impl Transmute {
|
||||
#[must_use]
|
||||
|
@ -579,6 +612,7 @@ impl<'tcx> LateLintPass<'tcx> for Transmute {
|
|||
| 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)
|
||||
|
|
Loading…
Reference in a new issue