@@ -21,8 +21,9 @@ use {rustc_ast as ast, rustc_hir as hir};
21
21
use crate :: lints:: {
22
22
AmbiguousWidePointerComparisons , AmbiguousWidePointerComparisonsAddrMetadataSuggestion ,
23
23
AmbiguousWidePointerComparisonsAddrSuggestion , AtomicOrderingFence , AtomicOrderingLoad ,
24
- AtomicOrderingStore , ImproperCTypes , InvalidAtomicOrderingDiag , InvalidNanComparisons ,
25
- InvalidNanComparisonsSuggestion , UnusedComparisons , VariantSizeDifferencesDiag ,
24
+ AtomicOrderingStore , ImproperCTypes , ImproperCTypesLayer , InvalidAtomicOrderingDiag ,
25
+ InvalidNanComparisons , InvalidNanComparisonsSuggestion , UnusedComparisons ,
26
+ VariantSizeDifferencesDiag ,
26
27
} ;
27
28
use crate :: { LateContext , LateLintPass , LintContext , fluent_generated as fluent} ;
28
29
@@ -593,7 +594,19 @@ struct CTypesVisitorState<'tcx> {
593
594
enum FfiResult < ' tcx > {
594
595
FfiSafe ,
595
596
FfiPhantom ( Ty < ' tcx > ) ,
596
- FfiUnsafe { ty : Ty < ' tcx > , reason : DiagMessage , help : Option < DiagMessage > } ,
597
+ FfiUnsafe {
598
+ ty : Ty < ' tcx > ,
599
+ reason : DiagMessage ,
600
+ help : Option < DiagMessage > ,
601
+ } ,
602
+ // NOTE: this `allow` is only here for one retroactively-added commit
603
+ #[ allow( dead_code) ]
604
+ FfiUnsafeWrapper {
605
+ ty : Ty < ' tcx > ,
606
+ reason : DiagMessage ,
607
+ help : Option < DiagMessage > ,
608
+ wrapped : Box < FfiResult < ' tcx > > ,
609
+ } ,
597
610
}
598
611
599
612
pub ( crate ) fn nonnull_optimization_guaranteed < ' tcx > (
@@ -803,12 +816,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
803
816
/// Check if the type is array and emit an unsafe type lint.
804
817
fn check_for_array_ty ( & mut self , sp : Span , ty : Ty < ' tcx > ) -> bool {
805
818
if let ty:: Array ( ..) = ty. kind ( ) {
806
- self . emit_ffi_unsafe_type_lint (
819
+ self . emit_ffi_unsafe_type_lint ( ty . clone ( ) , sp , vec ! [ ImproperCTypesLayer {
807
820
ty,
808
- sp,
809
- fluent:: lint_improper_ctypes_array_reason,
810
- Some ( fluent:: lint_improper_ctypes_array_help) ,
811
- ) ;
821
+ note: fluent:: lint_improper_ctypes_array_reason,
822
+ help: Some ( fluent:: lint_improper_ctypes_array_help) ,
823
+ inner_ty: None ,
824
+ span_note: None ,
825
+ } ] ) ;
812
826
true
813
827
} else {
814
828
false
@@ -865,9 +879,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
865
879
all_phantom &= match self . check_field_type_for_ffi ( acc, field, args) {
866
880
FfiSafe => false ,
867
881
// `()` fields are FFI-safe!
868
- FfiUnsafe { ty, .. } if ty. is_unit ( ) => false ,
882
+ FfiUnsafe { ty, .. } | FfiUnsafeWrapper { ty , .. } if ty. is_unit ( ) => false ,
869
883
FfiPhantom ( ..) => true ,
870
- r @ FfiUnsafe { .. } => return r,
884
+ r @ ( FfiUnsafe { .. } | FfiUnsafeWrapper { .. } ) => return r,
871
885
}
872
886
}
873
887
@@ -1155,8 +1169,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1155
1169
& mut self ,
1156
1170
ty : Ty < ' tcx > ,
1157
1171
sp : Span ,
1158
- note : DiagMessage ,
1159
- help : Option < DiagMessage > ,
1172
+ mut reasons : Vec < ImproperCTypesLayer < ' tcx > > ,
1160
1173
) {
1161
1174
let lint = match self . mode {
1162
1175
CItemKind :: Declaration => IMPROPER_CTYPES ,
@@ -1166,21 +1179,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1166
1179
CItemKind :: Declaration => "block" ,
1167
1180
CItemKind :: Definition => "fn" ,
1168
1181
} ;
1169
- let span_note = if let ty:: Adt ( def, _) = ty. kind ( )
1170
- && let Some ( sp) = self . cx . tcx . hir ( ) . span_if_local ( def. did ( ) )
1171
- {
1172
- Some ( sp)
1173
- } else {
1174
- None
1175
- } ;
1176
- self . cx . emit_span_lint ( lint, sp, ImproperCTypes {
1177
- ty,
1178
- desc,
1179
- label : sp,
1180
- help,
1181
- note,
1182
- span_note,
1183
- } ) ;
1182
+ for reason in reasons. iter_mut ( ) {
1183
+ reason. span_note = if let ty:: Adt ( def, _) = reason. ty . kind ( )
1184
+ && let Some ( sp) = self . cx . tcx . hir ( ) . span_if_local ( def. did ( ) )
1185
+ {
1186
+ Some ( sp)
1187
+ } else {
1188
+ None
1189
+ } ;
1190
+ }
1191
+
1192
+ self . cx . emit_span_lint ( lint, sp, ImproperCTypes { ty, desc, label : sp, reasons } ) ;
1184
1193
}
1185
1194
1186
1195
fn check_for_opaque_ty ( & mut self , sp : Span , ty : Ty < ' tcx > ) -> bool {
@@ -1209,7 +1218,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1209
1218
. visit_with ( & mut ProhibitOpaqueTypes )
1210
1219
. break_value ( )
1211
1220
{
1212
- self . emit_ffi_unsafe_type_lint ( ty, sp, fluent:: lint_improper_ctypes_opaque, None ) ;
1221
+ self . emit_ffi_unsafe_type_lint ( ty. clone ( ) , sp, vec ! [ ImproperCTypesLayer {
1222
+ ty,
1223
+ note: fluent:: lint_improper_ctypes_opaque,
1224
+ span_note: Some ( sp) ,
1225
+ help: None ,
1226
+ inner_ty: None ,
1227
+ } ] ) ;
1213
1228
true
1214
1229
} else {
1215
1230
false
@@ -1248,15 +1263,75 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1248
1263
match self . check_type_for_ffi ( & mut acc, ty) {
1249
1264
FfiResult :: FfiSafe => { }
1250
1265
FfiResult :: FfiPhantom ( ty) => {
1251
- self . emit_ffi_unsafe_type_lint (
1266
+ self . emit_ffi_unsafe_type_lint ( ty . clone ( ) , sp , vec ! [ ImproperCTypesLayer {
1252
1267
ty,
1253
- sp,
1254
- fluent:: lint_improper_ctypes_only_phantomdata,
1255
- None ,
1256
- ) ;
1268
+ note: fluent:: lint_improper_ctypes_only_phantomdata,
1269
+ span_note: None , // filled later
1270
+ help: None ,
1271
+ inner_ty: None ,
1272
+ } ] ) ;
1257
1273
}
1258
1274
FfiResult :: FfiUnsafe { ty, reason, help } => {
1259
- self . emit_ffi_unsafe_type_lint ( ty, sp, reason, help) ;
1275
+ self . emit_ffi_unsafe_type_lint ( ty. clone ( ) , sp, vec ! [ ImproperCTypesLayer {
1276
+ ty,
1277
+ help,
1278
+ note: reason,
1279
+ span_note: None , // filled later
1280
+ inner_ty: None ,
1281
+ } ] ) ;
1282
+ }
1283
+ ffir @ FfiResult :: FfiUnsafeWrapper { .. } => {
1284
+ let mut last_ty = None ;
1285
+ let mut ffiresult_recursor = Some ( & ffir) ;
1286
+ let mut cimproper_layers: Vec < ImproperCTypesLayer < ' tcx > > = vec ! [ ] ;
1287
+
1288
+ // this whole while block converts the arbitrarily-deep
1289
+ // FfiResult stack to a ImproperCTypesLayer Vec
1290
+ while let Some ( ref ffir_rec) = ffiresult_recursor {
1291
+ match ffir_rec {
1292
+ FfiResult :: FfiPhantom ( ty) => {
1293
+ last_ty = Some ( ty. clone ( ) ) ;
1294
+ let len = cimproper_layers. len ( ) ;
1295
+ if len > 0 {
1296
+ cimproper_layers[ len - 1 ] . inner_ty = last_ty. clone ( ) ;
1297
+ }
1298
+ cimproper_layers. push ( ImproperCTypesLayer {
1299
+ ty : ty. clone ( ) ,
1300
+ inner_ty : None ,
1301
+ help : None ,
1302
+ note : fluent:: lint_improper_ctypes_only_phantomdata,
1303
+ span_note : None , // filled later
1304
+ } ) ;
1305
+ ffiresult_recursor = None ;
1306
+ }
1307
+ FfiResult :: FfiUnsafe { ty, reason, help }
1308
+ | FfiResult :: FfiUnsafeWrapper { ty, reason, help, .. } => {
1309
+ last_ty = Some ( ty. clone ( ) ) ;
1310
+ let len = cimproper_layers. len ( ) ;
1311
+ if len > 0 {
1312
+ cimproper_layers[ len - 1 ] . inner_ty = last_ty. clone ( ) ;
1313
+ }
1314
+ cimproper_layers. push ( ImproperCTypesLayer {
1315
+ ty : ty. clone ( ) ,
1316
+ inner_ty : None ,
1317
+ help : help. clone ( ) ,
1318
+ note : reason. clone ( ) ,
1319
+ span_note : None , // filled later
1320
+ } ) ;
1321
+
1322
+ if let FfiResult :: FfiUnsafeWrapper { wrapped, .. } = ffir_rec {
1323
+ ffiresult_recursor = Some ( wrapped. as_ref ( ) ) ;
1324
+ } else {
1325
+ ffiresult_recursor = None ;
1326
+ }
1327
+ }
1328
+ FfiResult :: FfiSafe => {
1329
+ bug ! ( "malformed FfiResult stack: it should be unsafe all the way down" )
1330
+ }
1331
+ } ;
1332
+ }
1333
+ let last_ty = last_ty. unwrap ( ) ; // populated by any run of the `while` block
1334
+ self . emit_ffi_unsafe_type_lint ( last_ty, sp, cimproper_layers) ;
1260
1335
}
1261
1336
}
1262
1337
}
0 commit comments