Add new function_casts_as_integer lint
This commit is contained in:
parent
a7b3715826
commit
a23b8c48a5
5 changed files with 90 additions and 1 deletions
|
|
@ -265,6 +265,9 @@ lint_forgetting_copy_types = calls to `std::mem::forget` with a value that imple
|
|||
lint_forgetting_references = calls to `std::mem::forget` with a reference instead of an owned value does nothing
|
||||
.label = argument has type `{$arg_ty}`
|
||||
|
||||
lint_function_casts_as_integer = direct cast of function item into an integer
|
||||
.cast_as_fn = first cast to a function pointer `{$cast_from_ty}`
|
||||
|
||||
lint_hidden_glob_reexport = private item shadows public glob re-export
|
||||
.note_glob_reexport = the name `{$name}` in the {$namespace} namespace is supposed to be publicly re-exported here
|
||||
.note_private_item = but the private item here shadows it
|
||||
|
|
|
|||
62
compiler/rustc_lint/src/function_cast_as_integer.rs
Normal file
62
compiler/rustc_lint/src/function_cast_as_integer.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
use rustc_hir as hir;
|
||||
use rustc_middle::ty;
|
||||
use rustc_session::{declare_lint, declare_lint_pass};
|
||||
use rustc_span::BytePos;
|
||||
|
||||
use crate::lints::{FunctionCastsAsIntegerDiag, FunctionCastsAsIntegerSugg};
|
||||
use crate::{LateContext, LateLintPass};
|
||||
|
||||
declare_lint! {
|
||||
/// The `function_casts_as_integer` lint detects cases where a function item is casted
|
||||
/// into an integer.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// fn foo() {}
|
||||
/// let x = foo as usize;
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// When casting a function item into an integer, it's implicitly creating a
|
||||
/// function pointer that will in turn be casted into an integer. By making
|
||||
/// it explicit, it improves readability of the code and prevents bugs.
|
||||
pub FUNCTION_CASTS_AS_INTEGER,
|
||||
Warn,
|
||||
"casting a function into an integer",
|
||||
}
|
||||
|
||||
declare_lint_pass!(
|
||||
/// Lint for casts of functions into integers.
|
||||
FunctionCastsAsInteger => [FUNCTION_CASTS_AS_INTEGER]
|
||||
);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for FunctionCastsAsInteger {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
|
||||
let hir::ExprKind::Cast(cast_from_expr, cast_to_expr) = expr.kind else { return };
|
||||
let cast_to_ty = cx.typeck_results().expr_ty(expr);
|
||||
// Casting to a function (pointer?), so all good.
|
||||
if matches!(cast_to_ty.kind(), ty::FnDef(..) | ty::FnPtr(..)) {
|
||||
return;
|
||||
}
|
||||
let cast_from_ty = cx.typeck_results().expr_ty(cast_from_expr);
|
||||
if matches!(cast_from_ty.kind(), ty::FnDef(..)) {
|
||||
cx.tcx.emit_node_span_lint(
|
||||
FUNCTION_CASTS_AS_INTEGER,
|
||||
expr.hir_id,
|
||||
cast_to_expr.span.with_lo(cast_from_expr.span.hi() + BytePos(1)),
|
||||
FunctionCastsAsIntegerDiag {
|
||||
sugg: FunctionCastsAsIntegerSugg {
|
||||
suggestion: cast_from_expr.span.shrink_to_hi(),
|
||||
// We get the function pointer to have a nice display.
|
||||
cast_from_ty: cx.typeck_results().expr_ty_adjusted(cast_from_expr),
|
||||
cast_to_ty,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -45,6 +45,7 @@ mod errors;
|
|||
mod expect;
|
||||
mod for_loops_over_fallibles;
|
||||
mod foreign_modules;
|
||||
mod function_cast_as_integer;
|
||||
mod if_let_rescope;
|
||||
mod impl_trait_overcaptures;
|
||||
mod internal;
|
||||
|
|
@ -89,6 +90,7 @@ use deref_into_dyn_supertrait::*;
|
|||
use drop_forget_useless::*;
|
||||
use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
|
||||
use for_loops_over_fallibles::*;
|
||||
use function_cast_as_integer::*;
|
||||
use if_let_rescope::IfLetRescope;
|
||||
use impl_trait_overcaptures::ImplTraitOvercaptures;
|
||||
use internal::*;
|
||||
|
|
@ -241,6 +243,7 @@ late_lint_methods!(
|
|||
IfLetRescope: IfLetRescope::default(),
|
||||
StaticMutRefs: StaticMutRefs,
|
||||
UnqualifiedLocalImports: UnqualifiedLocalImports,
|
||||
FunctionCastsAsInteger: FunctionCastsAsInteger,
|
||||
CheckTransmutes: CheckTransmutes,
|
||||
LifetimeSyntax: LifetimeSyntax,
|
||||
]
|
||||
|
|
|
|||
|
|
@ -3019,6 +3019,27 @@ pub(crate) struct ReservedMultihash {
|
|||
pub suggestion: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_function_casts_as_integer)]
|
||||
pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> {
|
||||
#[subdiagnostic]
|
||||
pub(crate) sugg: FunctionCastsAsIntegerSugg<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(
|
||||
lint_cast_as_fn,
|
||||
code = " as {cast_from_ty}",
|
||||
applicability = "machine-applicable",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub(crate) struct FunctionCastsAsIntegerSugg<'tcx> {
|
||||
#[primary_span]
|
||||
pub suggestion: Span,
|
||||
pub cast_from_ty: Ty<'tcx>,
|
||||
pub cast_to_ty: Ty<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct MismatchedLifetimeSyntaxes {
|
||||
pub inputs: LifetimeSyntaxCategories<Vec<Span>>,
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ fn current_dll_path() -> Result<PathBuf, String> {
|
|||
|
||||
#[cfg(not(target_os = "aix"))]
|
||||
unsafe {
|
||||
let addr = current_dll_path as usize as *mut _;
|
||||
let addr = current_dll_path as fn() -> Result<PathBuf, String> as *mut _;
|
||||
let mut info = std::mem::zeroed();
|
||||
if libc::dladdr(addr, &mut info) == 0 {
|
||||
return Err("dladdr failed".into());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue