Skip to content

Commit 3770c8f

Browse files
committed
Limit local ADT types to size_of
Require all fields to be local
1 parent e998bb8 commit 3770c8f

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

clippy_lints/src/casts/cast_possible_truncation.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_errors::{Applicability, Diag, SuggestionStyle};
88
use rustc_hir::def::{DefKind, Res};
99
use rustc_hir::{BinOpKind, Expr, ExprKind, QPath};
1010
use rustc_lint::LateContext;
11-
use rustc_middle::ty::{self, FloatTy, Ty};
11+
use rustc_middle::ty::{self, FloatTy, Ty, TyCtxt};
1212
use rustc_span::symbol::sym;
1313
use rustc_span::Span;
1414
use rustc_target::abi::IntegerType;
@@ -100,6 +100,7 @@ fn apply_reductions(cx: &LateContext<'_>, nbits: u64, expr: &Expr<'_>, signed: b
100100
&& let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
101101
&& cx.tcx.is_diagnostic_item(sym::mem_size_of, def_id)
102102
&& let Some(ty) = cx.typeck_results().node_args(func.hir_id).types().next()
103+
&& is_valid_sizeof(cx.tcx, ty)
103104
&& let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty))
104105
{
105106
let size: u64 = layout.layout.size().bytes();
@@ -228,3 +229,23 @@ fn offer_suggestion(
228229
SuggestionStyle::ShowAlways,
229230
);
230231
}
232+
233+
// FIXME(@tesuji): May extend this to a validator functions to include:
234+
// * some ABI-guaranteed STD types,
235+
// * some non-local crate types suggested in [PR-12962][1].
236+
// [1]: https://github.com/rust-lang/rust-clippy/pull/12962#discussion_r1661500351
237+
fn is_valid_sizeof<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool {
238+
if ty.is_primitive_ty() || ty.is_any_ptr() || ty.is_box() || ty.is_slice() {
239+
return true;
240+
}
241+
if let ty::Adt(def, args) = ty.kind()
242+
&& def.did().is_local()
243+
{
244+
def.all_fields().all(|field| {
245+
let ty = field.ty(tcx, args);
246+
is_valid_sizeof(tcx, ty)
247+
})
248+
} else {
249+
false
250+
}
251+
}

tests/ui/cast.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,5 +511,11 @@ pub fn issue_9613() {
511511
CHUNK as u32;
512512
u64::MIN as u32;
513513
//~^ ERROR: casting `u64` to `u32` may truncate the value
514+
struct Foo(usize, u32);
515+
struct Bar(usize, String);
516+
core::mem::size_of::<Foo>() as u32;
517+
core::mem::size_of::<Bar>() as u32;
518+
//~^ ERROR: casting `usize` to `u32` may truncate
514519
core::mem::size_of::<String>() as u32;
520+
//~^ ERROR: casting `usize` to `u32` may truncate
515521
}

tests/ui/cast.stderr

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,7 @@ LL | u8::try_from(255 % 999999u64);
732732
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
733733

734734
error: casting `u64` to `u32` may truncate the value
735-
--> tests/ui/cast.rs:510:5
735+
--> tests/ui/cast.rs:512:5
736736
|
737737
LL | u64::MIN as u32;
738738
| ^^^^^^^^^^^^^^^
@@ -743,5 +743,29 @@ help: ... or use `try_from` and handle the error accordingly
743743
LL | u32::try_from(u64::MIN);
744744
| ~~~~~~~~~~~~~~~~~~~~~~~
745745

746-
error: aborting due to 93 previous errors
746+
error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers
747+
--> tests/ui/cast.rs:517:5
748+
|
749+
LL | core::mem::size_of::<Bar>() as u32;
750+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
751+
|
752+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
753+
help: ... or use `try_from` and handle the error accordingly
754+
|
755+
LL | u32::try_from(core::mem::size_of::<Bar>());
756+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
757+
758+
error: casting `usize` to `u32` may truncate the value on targets with 64-bit wide pointers
759+
--> tests/ui/cast.rs:519:5
760+
|
761+
LL | core::mem::size_of::<String>() as u32;
762+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
763+
|
764+
= help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ...
765+
help: ... or use `try_from` and handle the error accordingly
766+
|
767+
LL | u32::try_from(core::mem::size_of::<String>());
768+
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
769+
770+
error: aborting due to 95 previous errors
747771

0 commit comments

Comments
 (0)