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 ;
2
6
use rustc_hir:: { HirId , Item , ItemKind } ;
3
7
use rustc_lint:: { LateContext , LateLintPass } ;
8
+ use rustc_middle:: ty:: { Const , TyS } ;
4
9
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
5
10
use rustc_span:: sym;
6
11
@@ -37,15 +42,27 @@ impl<'tcx> LateLintPass<'tcx> for TrailingZeroSizedArrayWithoutRepr {
37
42
fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' tcx > ) {
38
43
dbg ! ( item. ident) ;
39
44
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
+ ) ;
49
66
}
50
67
}
51
68
}
@@ -58,19 +75,11 @@ fn is_struct_with_trailing_zero_sized_array(cx: &LateContext<'tcx>, item: &'tcx
58
75
if let ItemKind :: Struct ( data, _) = & item. kind {
59
76
if let Some ( last_field) = data. fields ( ) . last ( ) {
60
77
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 )
74
83
} else {
75
84
false
76
85
}
0 commit comments