@@ -2,12 +2,10 @@ use clippy_utils::{
22 diagnostics:: { span_lint_and_help, span_lint_and_sugg, span_lint_and_then} ,
33 source:: { indent_of, snippet} ,
44} ;
5- use rustc_ast:: Attribute ;
65use rustc_errors:: Applicability ;
76use rustc_hir:: { HirId , Item , ItemKind } ;
87use rustc_lint:: { LateContext , LateLintPass } ;
9- use rustc_middle:: dep_graph:: DepContext ;
10- use rustc_middle:: ty:: { self as ty_mod, Const , ReprFlags } ;
8+ use rustc_middle:: ty:: { Const , TyS } ;
119use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1210use rustc_span:: sym;
1311
@@ -43,18 +41,28 @@ declare_lint_pass!(TrailingZeroSizedArrayWithoutRepr => [TRAILING_ZERO_SIZED_ARR
4341impl < ' tcx > LateLintPass < ' tcx > for TrailingZeroSizedArrayWithoutRepr {
4442 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' tcx > ) {
4543 dbg ! ( item. ident) ;
46- if is_struct_with_trailing_zero_sized_array ( cx, item) && !has_repr_attr ( cx, item) {
47- eprintln ! ( "consider yourself linted 😎" ) ;
48- // span_lint_and_help(
49- // cx,
50- // TRAILING_ZERO_SIZED_ARRAY_WITHOUT_REPR,
51- // item.span,
52- // "trailing zero-sized array in a struct which is not marked with a `repr`
53- // attribute",
54- // None,
55- // "consider annotating the struct definition with `#[repr(C)]` or another
56- // `repr` attribute",
57- // );
44+ if is_struct_with_trailing_zero_sized_array ( cx, item) && !has_repr_attr ( cx, item. hir_id ( ) ) {
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+ ) ;
5866 }
5967 }
6068}
@@ -83,52 +91,9 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx
8391 }
8492}
8593
86- fn has_repr_attr ( cx : & LateContext < ' tcx > , item : & ' tcx Item < ' tcx > ) -> bool {
94+ fn has_repr_attr ( cx : & LateContext < ' tcx > , hir_id : HirId ) -> bool {
8795 // NOTE: there's at least four other ways to do this but I liked this one the best. (All five agreed
88- // on all testcases (when i wrote this comment. I added a few since then) .) Happy to use another;
96+ // on all testcases.) Happy to use another;
8997 // they're in the commit history if you want to look (or I can go find them).
90-
91- let attrs1 = cx. tcx . hir ( ) . attrs ( item. hir_id ( ) ) ;
92- let attrs2 = cx. tcx . get_attrs ( item. def_id . to_def_id ( ) ) ;
93-
94- let res11 = {
95- let sess = cx. tcx . sess ( ) ; // are captured values in closures evaluated once or every time?
96- attrs1
97- . iter ( )
98- . any ( |attr| !rustc_attr:: find_repr_attrs ( sess, attr) . is_empty ( ) )
99- } ;
100- let res12 = { attrs1. iter ( ) . any ( |attr| attr. has_name ( sym:: repr) ) } ;
101-
102- let res21 = {
103- let sess = cx. tcx . sess ( ) ; // are captured values in closures evaluated once or every time?
104- attrs2
105- . iter ( )
106- . any ( |attr| !rustc_attr:: find_repr_attrs ( sess, attr) . is_empty ( ) )
107- } ;
108- let res22 = { attrs2. iter ( ) . any ( |attr| attr. has_name ( sym:: repr) ) } ;
109-
110- let res_adt = {
111- let ty = cx. tcx . type_of ( item. def_id . to_def_id ( ) ) ;
112- if let ty_mod:: Adt ( adt, _) = ty. kind ( ) {
113- if adt. is_struct ( ) {
114- let repr = adt. repr ;
115- let repr_attr = ReprFlags :: IS_C | ReprFlags :: IS_TRANSPARENT | ReprFlags :: IS_SIMD | ReprFlags :: IS_LINEAR ;
116- repr. int . is_some ( ) || repr. align . is_some ( ) || repr. pack . is_some ( ) || repr. flags . intersects ( repr_attr)
117- } else {
118- false
119- }
120- } else {
121- false
122- }
123- } ;
124-
125- let all_same = ( res11 && res12 && res21 && res22 && res_adt) || ( !res11 && !res12 && !res21 && !res22 && !res_adt) ;
126-
127-
128- dbg ! ( (
129- ( res11, res12, res21, res22, res_adt) ,
130- all_same,
131- ) ) ;
132-
133- res12
98+ cx. tcx . hir ( ) . attrs ( hir_id) . iter ( ) . any ( |attr| attr. has_name ( sym:: repr) )
13499}
0 commit comments