Add primitive_method_to_numeric_cast lint
This commit is contained in:
parent
7fdded3e37
commit
be40534457
4 changed files with 88 additions and 0 deletions
|
|
@ -6068,6 +6068,7 @@ Released 2018-09-13
|
|||
[`possible_missing_comma`]: https://rust-lang.github.io/rust-clippy/master/index.html#possible_missing_comma
|
||||
[`precedence`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence
|
||||
[`precedence_bits`]: https://rust-lang.github.io/rust-clippy/master/index.html#precedence_bits
|
||||
[`primitive_method_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#primitive_method_to_numeric_cast
|
||||
[`print_in_format_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_in_format_impl
|
||||
[`print_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_literal
|
||||
[`print_stderr`]: https://rust-lang.github.io/rust-clippy/master/index.html#print_stderr
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ mod fn_to_numeric_cast;
|
|||
mod fn_to_numeric_cast_any;
|
||||
mod fn_to_numeric_cast_with_truncation;
|
||||
mod manual_dangling_ptr;
|
||||
mod primitive_method_to_numeric_cast;
|
||||
mod ptr_as_ptr;
|
||||
mod ptr_cast_constness;
|
||||
mod ref_as_ptr;
|
||||
|
|
@ -786,6 +787,32 @@ declare_clippy_lint! {
|
|||
"casting small constant literals to pointers to create dangling pointers"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
/// Checks for casts of a primitive method pointer to any integer type.
|
||||
///
|
||||
/// ### Why restrict this?
|
||||
/// Casting a function pointer to an integer can have surprising results and can occur
|
||||
/// accidentally if parentheses are omitted from a function call. If you aren't doing anything
|
||||
/// low-level with function pointers then you can opt out of casting functions to integers in
|
||||
/// order to avoid mistakes. Alternatively, you can use this lint to audit all uses of function
|
||||
/// pointer casts in your code.
|
||||
///
|
||||
/// ### Example
|
||||
/// ```no_run
|
||||
/// let _ = u16::max as usize;
|
||||
/// ```
|
||||
///
|
||||
/// Use instead:
|
||||
/// ```no_run
|
||||
/// let _ = u16::MAX as usize;
|
||||
/// ```
|
||||
#[clippy::version = "1.86.0"]
|
||||
pub PRIMITIVE_METHOD_TO_NUMERIC_CAST,
|
||||
suspicious,
|
||||
"casting a primitive method pointer to any integer type"
|
||||
}
|
||||
|
||||
pub struct Casts {
|
||||
msrv: Msrv,
|
||||
}
|
||||
|
|
@ -823,6 +850,7 @@ impl_lint_pass!(Casts => [
|
|||
REF_AS_PTR,
|
||||
AS_POINTER_UNDERSCORE,
|
||||
MANUAL_DANGLING_PTR,
|
||||
PRIMITIVE_METHOD_TO_NUMERIC_CAST,
|
||||
]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Casts {
|
||||
|
|
@ -847,6 +875,7 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
|
|||
ptr_cast_constness::check(cx, expr, cast_from_expr, cast_from, cast_to, self.msrv);
|
||||
as_ptr_cast_mut::check(cx, expr, cast_from_expr, cast_to);
|
||||
fn_to_numeric_cast_any::check(cx, expr, cast_from_expr, cast_from, cast_to);
|
||||
primitive_method_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to);
|
||||
fn_to_numeric_cast::check(cx, expr, cast_from_expr, cast_from, cast_to);
|
||||
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_from_expr, cast_from, cast_to);
|
||||
zero_ptr::check(cx, expr, cast_from_expr, cast_to_hir);
|
||||
|
|
|
|||
57
clippy_lints/src/casts/primitive_method_to_numeric_cast.rs
Normal file
57
clippy_lints/src/casts/primitive_method_to_numeric_cast.rs
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::match_def_path;
|
||||
use clippy_utils::source::snippet_with_applicability;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::Expr;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
||||
use super::PRIMITIVE_METHOD_TO_NUMERIC_CAST;
|
||||
|
||||
fn get_primitive_ty_name(ty: Ty<'_>) -> Option<&'static str> {
|
||||
match ty.kind() {
|
||||
ty::Char => Some("char"),
|
||||
ty::Int(int) => Some(int.name_str()),
|
||||
ty::Uint(uint) => Some(uint.name_str()),
|
||||
ty::Float(float) => Some(float.name_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
|
||||
// We allow casts from any function type to any function type.
|
||||
match cast_to.kind() {
|
||||
ty::FnDef(..) | ty::FnPtr(..) => return,
|
||||
_ => { /* continue to checks */ },
|
||||
}
|
||||
|
||||
if let ty::FnDef(def_id, generics) = cast_from.kind()
|
||||
&& let Some(method_name) = cx.tcx.opt_item_name(*def_id)
|
||||
&& let method_name = method_name.as_str()
|
||||
&& (method_name == "min" || method_name == "max")
|
||||
// We get the type on which the `min`/`max` method of the `Ord` trait is implemented.
|
||||
&& let [ty] = generics.as_slice()
|
||||
&& let Some(ty) = ty.as_type()
|
||||
// We get its name in case it's a primitive with an associated MIN/MAX constant.
|
||||
&& let Some(ty_name) = get_primitive_ty_name(ty)
|
||||
&& match_def_path(cx, *def_id, &["core", "cmp", "Ord", method_name])
|
||||
{
|
||||
let mut applicability = Applicability::MaybeIncorrect;
|
||||
let from_snippet = snippet_with_applicability(cx, cast_expr.span, "..", &mut applicability);
|
||||
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
PRIMITIVE_METHOD_TO_NUMERIC_CAST,
|
||||
expr.span,
|
||||
format!("casting function pointer `{from_snippet}` to `{cast_to}`"),
|
||||
|diag| {
|
||||
diag.span_suggestion_verbose(
|
||||
expr.span,
|
||||
"did you mean to use the associated constant?",
|
||||
format!("{ty_name}::{} as {cast_to}", method_name.to_ascii_uppercase()),
|
||||
applicability,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -68,6 +68,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
|
|||
crate::casts::FN_TO_NUMERIC_CAST_ANY_INFO,
|
||||
crate::casts::FN_TO_NUMERIC_CAST_WITH_TRUNCATION_INFO,
|
||||
crate::casts::MANUAL_DANGLING_PTR_INFO,
|
||||
crate::casts::PRIMITIVE_METHOD_TO_NUMERIC_CAST_INFO,
|
||||
crate::casts::PTR_AS_PTR_INFO,
|
||||
crate::casts::PTR_CAST_CONSTNESS_INFO,
|
||||
crate::casts::REF_AS_PTR_INFO,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue