about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNathaniel Hamovitz <18648574+nhamovitz@users.noreply.github.com>2021-10-15 16:16:27 -0700
committerNathaniel Hamovitz <18648574+nhamovitz@users.noreply.github.com>2021-10-18 03:05:18 -0700
commit7ee8e7a9b846686148b8797ecc5ae724a6c5a1a9 (patch)
treeb8085f5437b9cf2fca3635b14cb156e760a8494c
parent92d3b775bd05c363b69b91ed66c20904c7fbfbe7 (diff)
downloadrust-7ee8e7a9b846686148b8797ecc5ae724a6c5a1a9.tar.gz
rust-7ee8e7a9b846686148b8797ecc5ae724a6c5a1a9.zip
Implement detecting trailing zero-sized array
-rw-r--r--clippy_lints/src/lib.rs4
-rw-r--r--clippy_lints/src/trailing_zero_sized_array_without_repr_c.rs62
-rw-r--r--tests/ui/trailing_zero_sized_array_without_repr_c.rs26
3 files changed, 69 insertions, 23 deletions
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 6624ee93101..d494892c3b4 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -30,7 +30,6 @@ extern crate rustc_index;
 extern crate rustc_infer;
 extern crate rustc_lexer;
 extern crate rustc_lint;
-extern crate rustc_lint_defs;
 extern crate rustc_middle;
 extern crate rustc_mir_dataflow;
 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_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(await_holding_invalid::AwaitHolding));
     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(|| Box::new(match_str_case_mismatch::MatchStrCaseMismatch));
     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]
diff --git a/clippy_lints/src/trailing_zero_sized_array_without_repr_c.rs b/clippy_lints/src/trailing_zero_sized_array_without_repr_c.rs
index a96b8792295..6ca382d1679 100644
--- a/clippy_lints/src/trailing_zero_sized_array_without_repr_c.rs
+++ b/clippy_lints/src/trailing_zero_sized_array_without_repr_c.rs
@@ -1,6 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_lint_defs::Applicability;
+// use clippy_utils::is_integer_const;
+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};
 
 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`,
 //       e.g. store.register_early_pass(||
 // Box::new(trailing_zero_sized_array_without_repr_c::TrailingZeroSizedArrayWithoutReprC));
+// DONE!
 
-impl EarlyLintPass for TrailingZeroSizedArrayWithoutReprC {
-    fn check_struct_def(&mut self, cx: &EarlyContext<'_>, data: &rustc_ast::VariantData) {
-        if is_struct_with_trailing_zero_sized_array(cx, data) && !has_repr_c(cx, data) {
-            span_lint_and_sugg(
-                cx,
-                todo!(),
-                todo!(),
-                todo!(),
-                "try",
-                "`#[repr(C)]`".to_string(),
-                Applicability::MachineApplicable,
-            )
+impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutReprC {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        if is_struct_with_trailing_zero_sized_array(cx, item)
+        /* && !has_repr_c(cx, item) */
+        {
+            // span_lint_and_sugg(
+            //     cx,
+            //     todo!(),
+            //     todo!(),
+            //     todo!(),
+            //     "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 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 rustc_ast::ast::TyKind::Array(_, aconst) = &last_field.ty.kind;
-        // TODO: if array is zero-sized;
+        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
+            .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 {
-            dbg!(aconst);
+            eprintln!("true");
             true
         } else {
+            // dbg!(aconst);
+            eprintln!("false");
             false
         }
     }
 }
 
-fn has_repr_c(cx: &EarlyContext<'_>, data: &rustc_ast::VariantData) -> bool {
-    todo!()
+fn has_repr_c(cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) -> bool {
+    // todo!()
+    true
 }
diff --git a/tests/ui/trailing_zero_sized_array_without_repr_c.rs b/tests/ui/trailing_zero_sized_array_without_repr_c.rs
index 771622178e7..5f844f16ba1 100644
--- a/tests/ui/trailing_zero_sized_array_without_repr_c.rs
+++ b/tests/ui/trailing_zero_sized_array_without_repr_c.rs
@@ -20,4 +20,30 @@ struct GenericArrayType<T> {
     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() {}