mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 19:58:32 +00:00
Ran dev bless
!
This commit is contained in:
parent
4b4db59772
commit
b9948c4be6
@ -26,7 +26,7 @@ declare_clippy_lint! {
|
|||||||
/// Use instead:
|
/// Use instead:
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// #[repr(C)]
|
/// #[repr(C)]
|
||||||
/// struct MakesSense {
|
/// struct MoreOftenUseful {
|
||||||
/// some_field: usize,
|
/// some_field: usize,
|
||||||
/// last: [SomeType; 0],
|
/// last: [SomeType; 0],
|
||||||
/// }
|
/// }
|
||||||
@ -45,15 +45,13 @@ declare_lint_pass!(TrailingZeroSizedArrayWithoutReprC => [TRAILING_ZERO_SIZED_AR
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
|
impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
|
||||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
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) {
|
if is_struct_with_trailing_zero_sized_array(cx, item) && !has_repr_c(cx, item.def_id) {
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR_C,
|
TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR_C,
|
||||||
item.span,
|
item.span,
|
||||||
"trailing zero-sized array in a struct which is not marked `#[repr(C)]`",
|
"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, "..")),
|
format!("#[repr(C)]\n{}", snippet(cx, item.span, "..")),
|
||||||
Applicability::MaybeIncorrect,
|
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 {
|
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_chain! {
|
||||||
if let VariantData::Struct(field_defs, _) = data {
|
if let ItemKind::Struct(data, _generics) = &item.kind;
|
||||||
if let Some(last_field) = field_defs.last() {
|
if let VariantData::Struct(field_defs, _) = data;
|
||||||
if let TyKind::Array(_, aconst) = last_field.ty.kind {
|
if let Some(last_field) = field_defs.last();
|
||||||
let aconst_def_id = cx.tcx.hir().body_owner_def_id(aconst.body).to_def_id();
|
if let TyKind::Array(_, aconst) = last_field.ty.kind;
|
||||||
let ty = cx.tcx.type_of(aconst_def_id);
|
let aconst_def_id = cx.tcx.hir().body_owner_def_id(aconst.body).to_def_id();
|
||||||
let constant = cx
|
let ty = cx.tcx.type_of(aconst_def_id);
|
||||||
.tcx
|
let constant = cx
|
||||||
// NOTE: maybe const_eval_resolve? seems especially cursed to be using a const expr which
|
.tcx
|
||||||
// resolves to 0 to create a zero-sized array, tho
|
// NOTE: maybe const_eval_resolve?
|
||||||
.const_eval_poly(aconst_def_id)
|
.const_eval_poly(aconst_def_id)
|
||||||
.ok()
|
.ok()
|
||||||
.map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty));
|
.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 let Some(Constant::Int(val)) = constant.and_then(miri_to_const);
|
||||||
if val == 0 {
|
if val == 0;
|
||||||
// eprintln!("trailing: true");
|
then {
|
||||||
return true;
|
true
|
||||||
}
|
} else {
|
||||||
}
|
false
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// dbg!(aconst);
|
|
||||||
// eprintln!("trailing: false");
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_repr_c(cx: &LateContext<'tcx>, def_id: LocalDefId) -> bool {
|
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 hir_map = cx.tcx.hir();
|
||||||
let attrs = cx.tcx.hir().attrs(hir_id);
|
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?
|
// 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,
|
// other `repr` syms: repr, repr128, repr_align, repr_align_enum, repr_no_niche, repr_packed,
|
||||||
// repr_simd, repr_transparent
|
// repr_simd, repr_transparent
|
||||||
if let Some(_repr_attr) = attrs.iter().find(|attr| attr.has_name(sym::repr)) {
|
if let Some(_attr) = attrs.iter().find(|attr| attr.has_name(sym::repr)) {
|
||||||
// eprintln!("repr: true");
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
// eprintln!("repr: false");
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#![warn(clippy::trailing_zero_sized_array_without_repr_c)]
|
#![warn(clippy::trailing_zero_sized_array_without_repr_c)]
|
||||||
|
// #![feature(const_generics_defaults)] // see below
|
||||||
// #![feature(const_generics_defaults)]
|
|
||||||
|
|
||||||
struct RarelyUseful {
|
struct RarelyUseful {
|
||||||
field: i32,
|
field: i32,
|
||||||
@ -48,6 +47,9 @@ struct UsingFunction {
|
|||||||
last: [usize; compute_zero()],
|
last: [usize; compute_zero()],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: including these (along with the required feature) triggers an ICE. Should make sure the
|
||||||
|
// const generics people are aware of that if they weren't already.
|
||||||
|
|
||||||
// #[repr(C)]
|
// #[repr(C)]
|
||||||
// struct ConstParamOk<const N: usize = 0> {
|
// struct ConstParamOk<const N: usize = 0> {
|
||||||
// field: i32,
|
// field: i32,
|
||||||
@ -59,8 +61,7 @@ struct UsingFunction {
|
|||||||
// last: [usize; N]
|
// last: [usize; N]
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// TODO: actually, uh,, no idea what behavior here would be
|
||||||
// TODO: actually, uh,,
|
|
||||||
#[repr(packed)]
|
#[repr(packed)]
|
||||||
struct ReprPacked {
|
struct ReprPacked {
|
||||||
small: u8,
|
small: u8,
|
||||||
@ -68,20 +69,21 @@ struct ReprPacked {
|
|||||||
weird: [u64; 0],
|
weird: [u64; 0],
|
||||||
}
|
}
|
||||||
|
|
||||||
// same
|
// TODO: clarify expected behavior
|
||||||
#[repr(align(64))]
|
#[repr(align(64))]
|
||||||
struct ReprAlign {
|
struct ReprAlign {
|
||||||
field: i32,
|
field: i32,
|
||||||
last: [usize; 0],
|
last: [usize; 0],
|
||||||
}
|
}
|
||||||
|
|
||||||
// same
|
// TODO: clarify expected behavior
|
||||||
#[repr(C, align(64))]
|
#[repr(C, align(64))]
|
||||||
struct ReprCAlign {
|
struct ReprCAlign {
|
||||||
field: i32,
|
field: i32,
|
||||||
last: [usize; 0],
|
last: [usize; 0],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: because of https://doc.rust-lang.org/stable/reference/type-layout.html#primitive-representation-of-enums-with-fields and I'm not sure when in the compilation pipeline that would happen
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
enum DontLintAnonymousStructsFromDesuraging {
|
enum DontLintAnonymousStructsFromDesuraging {
|
||||||
A(u32),
|
A(u32),
|
||||||
@ -109,5 +111,4 @@ struct LotsOfFields {
|
|||||||
last: [usize; 0],
|
last: [usize; 0],
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {}
|
||||||
}
|
|
||||||
|
113
tests/ui/trailing_zero_sized_array_without_repr_c.stderr
Normal file
113
tests/ui/trailing_zero_sized_array_without_repr_c.stderr
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
|
||||||
|
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:4:1
|
||||||
|
|
|
||||||
|
LL | / struct RarelyUseful {
|
||||||
|
LL | | field: i32,
|
||||||
|
LL | | last: [usize; 0],
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
= note: `-D clippy::trailing-zero-sized-array-without-repr-c` implied by `-D warnings`
|
||||||
|
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
|
||||||
|
|
|
||||||
|
LL + #[repr(C)]
|
||||||
|
LL + struct RarelyUseful {
|
||||||
|
LL + field: i32,
|
||||||
|
LL + last: [usize; 0],
|
||||||
|
LL + }
|
||||||
|
|
|
||||||
|
|
||||||
|
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
|
||||||
|
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:15:1
|
||||||
|
|
|
||||||
|
LL | / struct OnlyFieldIsZeroSizeArray {
|
||||||
|
LL | | first_and_last: [usize; 0],
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
|
||||||
|
|
|
||||||
|
LL + #[repr(C)]
|
||||||
|
LL + struct OnlyFieldIsZeroSizeArray {
|
||||||
|
LL + first_and_last: [usize; 0],
|
||||||
|
LL + }
|
||||||
|
|
|
||||||
|
|
||||||
|
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
|
||||||
|
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:19:1
|
||||||
|
|
|
||||||
|
LL | / struct GenericArrayType<T> {
|
||||||
|
LL | | field: i32,
|
||||||
|
LL | | last: [T; 0],
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
|
||||||
|
|
|
||||||
|
LL + #[repr(C)]
|
||||||
|
LL + struct GenericArrayType<T> {
|
||||||
|
LL + field: i32,
|
||||||
|
LL + last: [T; 0],
|
||||||
|
LL + }
|
||||||
|
|
|
||||||
|
|
||||||
|
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
|
||||||
|
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:30:1
|
||||||
|
|
|
||||||
|
LL | / struct ZeroSizedFromExternalConst {
|
||||||
|
LL | | field: i32,
|
||||||
|
LL | | last: [usize; ZERO],
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
|
||||||
|
|
|
||||||
|
LL + #[repr(C)]
|
||||||
|
LL + struct ZeroSizedFromExternalConst {
|
||||||
|
LL + field: i32,
|
||||||
|
LL + last: [usize; ZERO],
|
||||||
|
LL + }
|
||||||
|
|
|
||||||
|
|
||||||
|
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
|
||||||
|
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:45:1
|
||||||
|
|
|
||||||
|
LL | / struct UsingFunction {
|
||||||
|
LL | | field: i32,
|
||||||
|
LL | | last: [usize; compute_zero()],
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
|
||||||
|
|
|
||||||
|
LL + #[repr(C)]
|
||||||
|
LL + struct UsingFunction {
|
||||||
|
LL + field: i32,
|
||||||
|
LL + last: [usize; compute_zero()],
|
||||||
|
LL + }
|
||||||
|
|
|
||||||
|
|
||||||
|
error: trailing zero-sized array in a struct which is not marked `#[repr(C)]`
|
||||||
|
--> $DIR/trailing_zero_sized_array_without_repr_c.rs:94:1
|
||||||
|
|
|
||||||
|
LL | / struct LotsOfFields {
|
||||||
|
LL | | f1: u32,
|
||||||
|
LL | | f2: u32,
|
||||||
|
LL | | f3: u32,
|
||||||
|
... |
|
||||||
|
LL | | last: [usize; 0],
|
||||||
|
LL | | }
|
||||||
|
| |_^
|
||||||
|
|
|
||||||
|
help: try annotating the struct definition with `#[repr(C)]` (or another `repr` attribute):
|
||||||
|
|
|
||||||
|
LL + #[repr(C)]
|
||||||
|
LL + struct LotsOfFields {
|
||||||
|
LL + f1: u32,
|
||||||
|
LL + f2: u32,
|
||||||
|
LL + f3: u32,
|
||||||
|
LL + f4: u32,
|
||||||
|
...
|
||||||
|
|
||||||
|
error: aborting due to 6 previous errors
|
||||||
|
|
Loading…
Reference in New Issue
Block a user