Ran dev bless!
This commit is contained in:
@@ -26,7 +26,7 @@ declare_clippy_lint! {
|
||||
/// Use instead:
|
||||
/// ```rust
|
||||
/// #[repr(C)]
|
||||
/// struct MakesSense {
|
||||
/// struct MoreOftenUseful {
|
||||
/// some_field: usize,
|
||||
/// last: [SomeType; 0],
|
||||
/// }
|
||||
@@ -45,15 +45,13 @@ declare_lint_pass!(TrailingZeroSizedArrayWithoutReprC => [TRAILING_ZERO_SIZED_AR
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||
dbg!(item.ident);
|
||||
|
||||
if is_struct_with_trailing_zero_sized_array(cx, item) && !has_repr_c(cx, item.def_id) {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR_C,
|
||||
item.span,
|
||||
"trailing zero-sized array in a struct which is not marked `#[repr(C)]`",
|
||||
"try",
|
||||
"try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):",
|
||||
format!("#[repr(C)]\n{}", snippet(cx, item.span, "..")),
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
@@ -62,46 +60,40 @@ impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
|
||||
}
|
||||
|
||||
fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool {
|
||||
if let ItemKind::Struct(data, _generics) = &item.kind {
|
||||
if let VariantData::Struct(field_defs, _) = data {
|
||||
if let Some(last_field) = field_defs.last() {
|
||||
if let TyKind::Array(_, aconst) = last_field.ty.kind {
|
||||
let aconst_def_id = cx.tcx.hir().body_owner_def_id(aconst.body).to_def_id();
|
||||
let ty = cx.tcx.type_of(aconst_def_id);
|
||||
let constant = cx
|
||||
.tcx
|
||||
// NOTE: maybe const_eval_resolve? seems especially cursed to be using a const expr which
|
||||
// resolves to 0 to create a zero-sized array, tho
|
||||
.const_eval_poly(aconst_def_id)
|
||||
.ok()
|
||||
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
|
||||
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) {
|
||||
if val == 0 {
|
||||
// eprintln!("trailing: true");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if_chain! {
|
||||
if let ItemKind::Struct(data, _generics) = &item.kind;
|
||||
if let VariantData::Struct(field_defs, _) = data;
|
||||
if let Some(last_field) = field_defs.last();
|
||||
if let TyKind::Array(_, aconst) = last_field.ty.kind;
|
||||
let aconst_def_id = cx.tcx.hir().body_owner_def_id(aconst.body).to_def_id();
|
||||
let ty = cx.tcx.type_of(aconst_def_id);
|
||||
let constant = cx
|
||||
.tcx
|
||||
// NOTE: maybe const_eval_resolve?
|
||||
.const_eval_poly(aconst_def_id)
|
||||
.ok()
|
||||
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
|
||||
if let Some(Constant::Int(val)) = constant.and_then(miri_to_const);
|
||||
if val == 0;
|
||||
then {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
// dbg!(aconst);
|
||||
// eprintln!("trailing: false");
|
||||
false
|
||||
}
|
||||
|
||||
fn has_repr_c(cx: &LateContext<'tcx>, def_id: LocalDefId) -> bool {
|
||||
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
|
||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
||||
let hir_map = cx.tcx.hir();
|
||||
let hir_id = hir_map.local_def_id_to_hir_id(def_id);
|
||||
let attrs = hir_map.attrs(hir_id);
|
||||
|
||||
// NOTE: Can there ever be more than one `repr` attribute?
|
||||
// other `repr` syms: repr, repr128, repr_align, repr_align_enum, repr_no_niche, repr_packed,
|
||||
// repr_simd, repr_transparent
|
||||
if let Some(_repr_attr) = attrs.iter().find(|attr| attr.has_name(sym::repr)) {
|
||||
// eprintln!("repr: true");
|
||||
if let Some(_attr) = attrs.iter().find(|attr| attr.has_name(sym::repr)) {
|
||||
true
|
||||
} else {
|
||||
// eprintln!("repr: false");
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user