1 //! lint on C-like enums that are `repr(isize/usize)` and have values that
2 //! don't fit into an `i32`
4 use clippy_utils
::consts
::{mir_to_const, Constant}
;
5 use clippy_utils
::diagnostics
::span_lint
;
6 use rustc_hir
::{Item, ItemKind}
;
7 use rustc_lint
::{LateContext, LateLintPass}
;
8 use rustc_middle
::ty
::util
::IntTypeExt
;
9 use rustc_middle
::ty
::{self, IntTy, UintTy}
;
10 use rustc_session
::declare_lint_pass
;
12 declare_clippy_lint
! {
14 /// Checks for C-like enumerations that are
15 /// `repr(isize/usize)` and have values that don't fit into an `i32`.
17 /// ### Why is this bad?
18 /// This will truncate the variant value on 32 bit
19 /// architectures, but works fine on 64 bit.
23 /// # #[cfg(target_pointer_width = "64")]
25 /// enum NonPortable {
26 /// X = 0x1_0000_0000,
30 #[clippy::version = "pre 1.29.0"]
31 pub ENUM_CLIKE_UNPORTABLE_VARIANT
,
33 "C-like enums that are `repr(isize/usize)` and have values that don't fit into an `i32`"
36 declare_lint_pass
!(UnportableVariant
=> [ENUM_CLIKE_UNPORTABLE_VARIANT
]);
38 impl<'tcx
> LateLintPass
<'tcx
> for UnportableVariant
{
39 #[expect(clippy::cast_possible_wrap)]
40 fn check_item(&mut self, cx
: &LateContext
<'tcx
>, item
: &'tcx Item
<'_
>) {
41 if cx
.tcx
.data_layout
.pointer_size
.bits() != 64 {
44 if let ItemKind
::Enum(def
, _
) = &item
.kind
{
45 for var
in def
.variants
{
46 if let Some(anon_const
) = &var
.disr_expr
{
47 let def_id
= cx
.tcx
.hir().body_owner_def_id(anon_const
.body
);
48 let mut ty
= cx
.tcx
.type_of(def_id
.to_def_id()).instantiate_identity();
51 .const_eval_poly(def_id
.to_def_id())
53 .map(|val
| rustc_middle
::mir
::Const
::from_value(val
, ty
));
54 if let Some(Constant
::Int(val
)) = constant
.and_then(|c
| mir_to_const(cx
, c
)) {
55 if let ty
::Adt(adt
, _
) = ty
.kind() {
57 ty
= adt
.repr().discr_type().to_ty(cx
.tcx
);
61 ty
::Int(IntTy
::Isize
) => {
62 let val
= ((val
as i128
) << 64) >> 64;
63 if i32::try_from(val
).is_ok() {
67 ty
::Uint(UintTy
::Usize
) if val
> u128
::from(u32::MAX
) => {}
,
72 ENUM_CLIKE_UNPORTABLE_VARIANT
,
74 "C-like enum variant discriminant is not portable to 32-bit targets",