@@ -22,10 +22,10 @@ mod improper_ctypes;
22
22
use crate :: lints:: {
23
23
AmbiguousWidePointerComparisons , AmbiguousWidePointerComparisonsAddrMetadataSuggestion ,
24
24
AmbiguousWidePointerComparisonsAddrSuggestion , AtomicOrderingFence , AtomicOrderingLoad ,
25
- AtomicOrderingStore , ImproperCTypes , InvalidAtomicOrderingDiag , InvalidNanComparisons ,
26
- InvalidNanComparisonsSuggestion , UnpredictableFunctionPointerComparisons ,
27
- UnpredictableFunctionPointerComparisonsSuggestion , UnusedComparisons ,
28
- VariantSizeDifferencesDiag ,
25
+ AtomicOrderingStore , ImproperCTypes , ImproperCTypesLayer , InvalidAtomicOrderingDiag ,
26
+ InvalidNanComparisons , InvalidNanComparisonsSuggestion ,
27
+ UnpredictableFunctionPointerComparisons , UnpredictableFunctionPointerComparisonsSuggestion ,
28
+ UnusedComparisons , VariantSizeDifferencesDiag ,
29
29
} ;
30
30
use crate :: { LateContext , LateLintPass , LintContext , fluent_generated as fluent} ;
31
31
@@ -727,7 +727,19 @@ struct CTypesVisitorState<'tcx> {
727
727
enum FfiResult < ' tcx > {
728
728
FfiSafe ,
729
729
FfiPhantom ( Ty < ' tcx > ) ,
730
- FfiUnsafe { ty : Ty < ' tcx > , reason : DiagMessage , help : Option < DiagMessage > } ,
730
+ FfiUnsafe {
731
+ ty : Ty < ' tcx > ,
732
+ reason : DiagMessage ,
733
+ help : Option < DiagMessage > ,
734
+ } ,
735
+ // NOTE: this `allow` is only here for one retroactively-added commit
736
+ #[ allow( dead_code) ]
737
+ FfiUnsafeWrapper {
738
+ ty : Ty < ' tcx > ,
739
+ reason : DiagMessage ,
740
+ help : Option < DiagMessage > ,
741
+ wrapped : Box < FfiResult < ' tcx > > ,
742
+ } ,
731
743
}
732
744
733
745
pub ( crate ) fn nonnull_optimization_guaranteed < ' tcx > (
@@ -933,12 +945,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
933
945
/// Check if the type is array and emit an unsafe type lint.
934
946
fn check_for_array_ty ( & mut self , sp : Span , ty : Ty < ' tcx > ) -> bool {
935
947
if let ty:: Array ( ..) = ty. kind ( ) {
936
- self . emit_ffi_unsafe_type_lint (
948
+ self . emit_ffi_unsafe_type_lint ( ty . clone ( ) , sp , vec ! [ ImproperCTypesLayer {
937
949
ty,
938
- sp,
939
- fluent:: lint_improper_ctypes_array_reason,
940
- Some ( fluent:: lint_improper_ctypes_array_help) ,
941
- ) ;
950
+ note: fluent:: lint_improper_ctypes_array_reason,
951
+ help: Some ( fluent:: lint_improper_ctypes_array_help) ,
952
+ inner_ty: None ,
953
+ span_note: None ,
954
+ } ] ) ;
942
955
true
943
956
} else {
944
957
false
@@ -995,9 +1008,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
995
1008
all_phantom &= match self . check_field_type_for_ffi ( acc, field, args) {
996
1009
FfiSafe => false ,
997
1010
// `()` fields are FFI-safe!
998
- FfiUnsafe { ty, .. } if ty. is_unit ( ) => false ,
1011
+ FfiUnsafe { ty, .. } | FfiUnsafeWrapper { ty , .. } if ty. is_unit ( ) => false ,
999
1012
FfiPhantom ( ..) => true ,
1000
- r @ FfiUnsafe { .. } => return r,
1013
+ r @ ( FfiUnsafe { .. } | FfiUnsafeWrapper { .. } ) => return r,
1001
1014
}
1002
1015
}
1003
1016
@@ -1278,8 +1291,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1278
1291
& mut self ,
1279
1292
ty : Ty < ' tcx > ,
1280
1293
sp : Span ,
1281
- note : DiagMessage ,
1282
- help : Option < DiagMessage > ,
1294
+ mut reasons : Vec < ImproperCTypesLayer < ' tcx > > ,
1283
1295
) {
1284
1296
let lint = match self . mode {
1285
1297
CItemKind :: Declaration => IMPROPER_CTYPES ,
@@ -1289,21 +1301,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1289
1301
CItemKind :: Declaration => "block" ,
1290
1302
CItemKind :: Definition => "fn" ,
1291
1303
} ;
1292
- let span_note = if let ty:: Adt ( def, _) = ty. kind ( )
1293
- && let Some ( sp) = self . cx . tcx . hir ( ) . span_if_local ( def. did ( ) )
1294
- {
1295
- Some ( sp)
1296
- } else {
1297
- None
1298
- } ;
1299
- self . cx . emit_span_lint ( lint, sp, ImproperCTypes {
1300
- ty,
1301
- desc,
1302
- label : sp,
1303
- help,
1304
- note,
1305
- span_note,
1306
- } ) ;
1304
+ for reason in reasons. iter_mut ( ) {
1305
+ reason. span_note = if let ty:: Adt ( def, _) = reason. ty . kind ( )
1306
+ && let Some ( sp) = self . cx . tcx . hir ( ) . span_if_local ( def. did ( ) )
1307
+ {
1308
+ Some ( sp)
1309
+ } else {
1310
+ None
1311
+ } ;
1312
+ }
1313
+
1314
+ self . cx . emit_span_lint ( lint, sp, ImproperCTypes { ty, desc, label : sp, reasons } ) ;
1307
1315
}
1308
1316
1309
1317
fn check_for_opaque_ty ( & mut self , sp : Span , ty : Ty < ' tcx > ) -> bool {
@@ -1332,7 +1340,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1332
1340
. visit_with ( & mut ProhibitOpaqueTypes )
1333
1341
. break_value ( )
1334
1342
{
1335
- self . emit_ffi_unsafe_type_lint ( ty, sp, fluent:: lint_improper_ctypes_opaque, None ) ;
1343
+ self . emit_ffi_unsafe_type_lint ( ty. clone ( ) , sp, vec ! [ ImproperCTypesLayer {
1344
+ ty,
1345
+ note: fluent:: lint_improper_ctypes_opaque,
1346
+ span_note: Some ( sp) ,
1347
+ help: None ,
1348
+ inner_ty: None ,
1349
+ } ] ) ;
1336
1350
true
1337
1351
} else {
1338
1352
false
@@ -1371,15 +1385,75 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1371
1385
match self . check_type_for_ffi ( & mut acc, ty) {
1372
1386
FfiResult :: FfiSafe => { }
1373
1387
FfiResult :: FfiPhantom ( ty) => {
1374
- self . emit_ffi_unsafe_type_lint (
1388
+ self . emit_ffi_unsafe_type_lint ( ty . clone ( ) , sp , vec ! [ ImproperCTypesLayer {
1375
1389
ty,
1376
- sp,
1377
- fluent:: lint_improper_ctypes_only_phantomdata,
1378
- None ,
1379
- ) ;
1390
+ note: fluent:: lint_improper_ctypes_only_phantomdata,
1391
+ span_note: None , // filled later
1392
+ help: None ,
1393
+ inner_ty: None ,
1394
+ } ] ) ;
1380
1395
}
1381
1396
FfiResult :: FfiUnsafe { ty, reason, help } => {
1382
- self . emit_ffi_unsafe_type_lint ( ty, sp, reason, help) ;
1397
+ self . emit_ffi_unsafe_type_lint ( ty. clone ( ) , sp, vec ! [ ImproperCTypesLayer {
1398
+ ty,
1399
+ help,
1400
+ note: reason,
1401
+ span_note: None , // filled later
1402
+ inner_ty: None ,
1403
+ } ] ) ;
1404
+ }
1405
+ ffir @ FfiResult :: FfiUnsafeWrapper { .. } => {
1406
+ let mut last_ty = None ;
1407
+ let mut ffiresult_recursor = Some ( & ffir) ;
1408
+ let mut cimproper_layers: Vec < ImproperCTypesLayer < ' tcx > > = vec ! [ ] ;
1409
+
1410
+ // this whole while block converts the arbitrarily-deep
1411
+ // FfiResult stack to a ImproperCTypesLayer Vec
1412
+ while let Some ( ref ffir_rec) = ffiresult_recursor {
1413
+ match ffir_rec {
1414
+ FfiResult :: FfiPhantom ( ty) => {
1415
+ last_ty = Some ( ty. clone ( ) ) ;
1416
+ let len = cimproper_layers. len ( ) ;
1417
+ if len > 0 {
1418
+ cimproper_layers[ len - 1 ] . inner_ty = last_ty. clone ( ) ;
1419
+ }
1420
+ cimproper_layers. push ( ImproperCTypesLayer {
1421
+ ty : ty. clone ( ) ,
1422
+ inner_ty : None ,
1423
+ help : None ,
1424
+ note : fluent:: lint_improper_ctypes_only_phantomdata,
1425
+ span_note : None , // filled later
1426
+ } ) ;
1427
+ ffiresult_recursor = None ;
1428
+ }
1429
+ FfiResult :: FfiUnsafe { ty, reason, help }
1430
+ | FfiResult :: FfiUnsafeWrapper { ty, reason, help, .. } => {
1431
+ last_ty = Some ( ty. clone ( ) ) ;
1432
+ let len = cimproper_layers. len ( ) ;
1433
+ if len > 0 {
1434
+ cimproper_layers[ len - 1 ] . inner_ty = last_ty. clone ( ) ;
1435
+ }
1436
+ cimproper_layers. push ( ImproperCTypesLayer {
1437
+ ty : ty. clone ( ) ,
1438
+ inner_ty : None ,
1439
+ help : help. clone ( ) ,
1440
+ note : reason. clone ( ) ,
1441
+ span_note : None , // filled later
1442
+ } ) ;
1443
+
1444
+ if let FfiResult :: FfiUnsafeWrapper { wrapped, .. } = ffir_rec {
1445
+ ffiresult_recursor = Some ( wrapped. as_ref ( ) ) ;
1446
+ } else {
1447
+ ffiresult_recursor = None ;
1448
+ }
1449
+ }
1450
+ FfiResult :: FfiSafe => {
1451
+ bug ! ( "malformed FfiResult stack: it should be unsafe all the way down" )
1452
+ }
1453
+ } ;
1454
+ }
1455
+ let last_ty = last_ty. unwrap ( ) ; // populated by any run of the `while` block
1456
+ self . emit_ffi_unsafe_type_lint ( last_ty, sp, cimproper_layers) ;
1383
1457
}
1384
1458
}
1385
1459
}
0 commit comments