1- use clippy_utils:: { consts:: miri_to_const, consts:: Constant , diagnostics:: span_lint_and_help} ;
1+ use clippy_utils:: {
2+ diagnostics:: { span_lint_and_help, span_lint_and_sugg, span_lint_and_then} ,
3+ source:: { indent_of, snippet} ,
4+ } ;
5+ use rustc_errors:: Applicability ;
26use rustc_hir:: { HirId , Item , ItemKind } ;
37use rustc_lint:: { LateContext , LateLintPass } ;
8+ use rustc_middle:: ty:: { Const , TyS } ;
49use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
510use rustc_span:: sym;
611
@@ -37,15 +42,27 @@ impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutRepr {
3742 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' tcx > ) {
3843 dbg ! ( item. ident) ;
3944 if is_struct_with_trailing_zero_sized_array ( cx, item) && !has_repr_attr ( cx, item. hir_id ( ) ) {
40- // span_lint_and_help(
41- // cx,
42- // TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR,
43- // item.span,
44- // "trailing zero-sized array in a struct which is not marked with a `repr` attribute",
45- // None,
46- // "",
47- // );
48- eprintln ! ( "consider yourself linted 😎" ) ;
45+ let help_msg = format ! (
46+ "consider annotating {} with `#[repr(C)]` or another `repr` attribute" ,
47+ cx. tcx
48+ . type_of( item. def_id)
49+ . ty_adt_def( )
50+ . map( |adt_def| cx. tcx. def_path_str( adt_def. did) )
51+ . unwrap_or_else(
52+ // I don't think this will ever be the case, since we made it through
53+ // `is_struct_with_trailing_zero_sized_array`, but I don't feel comfortable putting an `unwrap`
54+ || "the struct definition" . to_string( )
55+ )
56+ ) ;
57+
58+ span_lint_and_help (
59+ cx,
60+ TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR ,
61+ item. span ,
62+ "trailing zero-sized array in a struct which is not marked with a `repr` attribute" ,
63+ None ,
64+ & help_msg,
65+ ) ;
4966 }
5067 }
5168}
@@ -58,19 +75,11 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx
5875 if let ItemKind :: Struct ( data, _) = & item. kind {
5976 if let Some ( last_field) = data. fields ( ) . last ( ) {
6077 if let rustc_hir:: TyKind :: Array ( _, length) = last_field. ty . kind {
61- let length_did = cx. tcx . hir ( ) . body_owner_def_id ( length. body ) . to_def_id ( ) ;
62- let ty = cx. tcx . type_of ( length_did) ;
63- let length = cx
64- . tcx
65- // ICE happens in `const_eval_poly` according to my backtrace
66- . const_eval_poly ( length_did)
67- . ok ( )
68- . map ( |val| rustc_middle:: ty:: Const :: from_value ( cx. tcx , val, ty) ) ;
69- if let Some ( Constant :: Int ( length) ) = length. and_then ( miri_to_const) {
70- length == 0
71- } else {
72- false
73- }
78+ // Then check if that that array zero-sized
79+ let length_ldid = cx. tcx . hir ( ) . local_def_id ( length. hir_id ) ;
80+ let length = Const :: from_anon_const ( cx. tcx , length_ldid) ;
81+ let length = length. try_eval_usize ( cx. tcx , cx. param_env ) ;
82+ length == Some ( 0 )
7483 } else {
7584 false
7685 }
0 commit comments