mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-12-01 00:49:30 +00:00
Implement detecting trailing zero-sized array
This commit is contained in:
parent
92d3b775bd
commit
7ee8e7a9b8
3 changed files with 69 additions and 23 deletions
|
@ -30,7 +30,6 @@ extern crate rustc_index;
|
||||||
extern crate rustc_infer;
|
extern crate rustc_infer;
|
||||||
extern crate rustc_lexer;
|
extern crate rustc_lexer;
|
||||||
extern crate rustc_lint;
|
extern crate rustc_lint;
|
||||||
extern crate rustc_lint_defs;
|
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
extern crate rustc_mir_dataflow;
|
extern crate rustc_mir_dataflow;
|
||||||
extern crate rustc_parse;
|
extern crate rustc_parse;
|
||||||
|
@ -488,7 +487,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
store.register_late_pass(|| Box::new(utils::internal_lints::OuterExpnDataPass));
|
store.register_late_pass(|| Box::new(utils::internal_lints::OuterExpnDataPass));
|
||||||
}
|
}
|
||||||
|
|
||||||
store.register_early_pass(|| Box::new(trailing_zero_sized_array_without_repr_c::TrailingZeroSizedArrayWithoutReprC));
|
|
||||||
store.register_late_pass(|| Box::new(utils::author::Author));
|
store.register_late_pass(|| Box::new(utils::author::Author));
|
||||||
store.register_late_pass(|| Box::new(await_holding_invalid::AwaitHolding));
|
store.register_late_pass(|| Box::new(await_holding_invalid::AwaitHolding));
|
||||||
store.register_late_pass(|| Box::new(serde_api::SerdeApi));
|
store.register_late_pass(|| Box::new(serde_api::SerdeApi));
|
||||||
|
@ -780,6 +778,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
||||||
store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::default()));
|
store.register_late_pass(move || Box::new(undocumented_unsafe_blocks::UndocumentedUnsafeBlocks::default()));
|
||||||
store.register_late_pass(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch));
|
store.register_late_pass(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch));
|
||||||
store.register_late_pass(move || Box::new(format_args::FormatArgs));
|
store.register_late_pass(move || Box::new(format_args::FormatArgs));
|
||||||
|
store.register_late_pass(|| Box::new(trailing_zero_sized_array_without_repr_c::TrailingZeroSizedArrayWithoutReprC));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
// use clippy_utils::is_integer_const;
|
||||||
use rustc_lint_defs::Applicability;
|
use clippy_utils::consts::{miri_to_const, Constant};
|
||||||
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir::{Item, ItemKind, TyKind, VariantData};
|
||||||
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
|
@ -36,38 +39,55 @@ declare_lint_pass!(TrailingZeroSizedArrayWithoutReprC => [TRAILING_ZERO_SIZED_AR
|
||||||
// TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
|
// TODO: Register the lint pass in `clippy_lints/src/lib.rs`,
|
||||||
// e.g. store.register_early_pass(||
|
// e.g. store.register_early_pass(||
|
||||||
// Box::new(trailing_zero_sized_array_without_repr_c::TrailingZeroSizedArrayWithoutReprC));
|
// Box::new(trailing_zero_sized_array_without_repr_c::TrailingZeroSizedArrayWithoutReprC));
|
||||||
|
// DONE!
|
||||||
|
|
||||||
impl EarlyLintPass for TrailingZeroSizedArrayWithoutReprC {
|
impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
|
||||||
fn check_struct_def(&mut self, cx: &EarlyContext<'_>, data: &rustc_ast::VariantData) {
|
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
|
||||||
if is_struct_with_trailing_zero_sized_array(cx, data) && !has_repr_c(cx, data) {
|
if is_struct_with_trailing_zero_sized_array(cx, item)
|
||||||
span_lint_and_sugg(
|
/* && !has_repr_c(cx, item) */
|
||||||
cx,
|
{
|
||||||
todo!(),
|
// span_lint_and_sugg(
|
||||||
todo!(),
|
// cx,
|
||||||
todo!(),
|
// todo!(),
|
||||||
"try",
|
// todo!(),
|
||||||
"`#[repr(C)]`".to_string(),
|
// todo!(),
|
||||||
Applicability::MachineApplicable,
|
// "try",
|
||||||
)
|
// "`#[repr(C)]`".to_string(),
|
||||||
|
// Applicability::MachineApplicable,
|
||||||
|
// );
|
||||||
|
// println!("consider yourself linted 😎");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_struct_with_trailing_zero_sized_array(cx: &EarlyContext<'_>, data: &rustc_ast::VariantData) -> bool {
|
fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool {
|
||||||
|
dbg!(item.ident);
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let rustc_ast::ast::VariantData::Struct(field_defs, some_bool_huh) = data;
|
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 Some(last_field) = field_defs.last();
|
||||||
if let rustc_ast::ast::TyKind::Array(_, aconst) = &last_field.ty.kind;
|
if let TyKind::Array(_, aconst) = last_field.ty.kind;
|
||||||
// TODO: if array is zero-sized;
|
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
|
||||||
|
.const_eval_poly(aconst_def_id) // 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
|
||||||
|
.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 {
|
then {
|
||||||
dbg!(aconst);
|
eprintln!("true");
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
// dbg!(aconst);
|
||||||
|
eprintln!("false");
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_repr_c(cx: &EarlyContext<'_>, data: &rustc_ast::VariantData) -> bool {
|
fn has_repr_c(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool {
|
||||||
todo!()
|
// todo!()
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,4 +20,30 @@ struct GenericArrayType<T> {
|
||||||
last: [T; 0],
|
last: [T; 0],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SizedArray {
|
||||||
|
field: i32,
|
||||||
|
last: [usize; 1],
|
||||||
|
}
|
||||||
|
|
||||||
|
const ZERO: usize = 0;
|
||||||
|
struct ZeroSizedFromExternalConst {
|
||||||
|
field: i32,
|
||||||
|
last: [usize; ZERO],
|
||||||
|
}
|
||||||
|
|
||||||
|
const ONE: usize = 1;
|
||||||
|
struct NonZeroSizedFromExternalConst {
|
||||||
|
field: i32,
|
||||||
|
last: [usize; ONE],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::eq_op)] // lmao im impressed
|
||||||
|
const fn compute_zero() -> usize {
|
||||||
|
(4 + 6) - (2 * 5)
|
||||||
|
}
|
||||||
|
struct UsingFunction {
|
||||||
|
field: i32,
|
||||||
|
last: [usize; compute_zero()],
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
Loading…
Reference in a new issue