@@ -22,10 +22,10 @@ mod improper_ctypes;
2222use crate :: lints:: {
2323 AmbiguousWidePointerComparisons , AmbiguousWidePointerComparisonsAddrMetadataSuggestion ,
2424 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 ,
2929} ;
3030use crate :: { LateContext , LateLintPass , LintContext , fluent_generated as fluent} ;
3131
@@ -727,7 +727,19 @@ struct CTypesVisitorState<'tcx> {
727727enum FfiResult < ' tcx > {
728728 FfiSafe ,
729729 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+ } ,
731743}
732744
733745pub ( crate ) fn nonnull_optimization_guaranteed < ' tcx > (
@@ -933,12 +945,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
933945 /// Check if the type is array and emit an unsafe type lint.
934946 fn check_for_array_ty ( & mut self , sp : Span , ty : Ty < ' tcx > ) -> bool {
935947 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 {
937949 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+ } ] ) ;
942955 true
943956 } else {
944957 false
@@ -995,9 +1008,9 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
9951008 all_phantom &= match self . check_field_type_for_ffi ( acc, field, args) {
9961009 FfiSafe => false ,
9971010 // `()` fields are FFI-safe!
998- FfiUnsafe { ty, .. } if ty. is_unit ( ) => false ,
1011+ FfiUnsafe { ty, .. } | FfiUnsafeWrapper { ty , .. } if ty. is_unit ( ) => false ,
9991012 FfiPhantom ( ..) => true ,
1000- r @ FfiUnsafe { .. } => return r,
1013+ r @ ( FfiUnsafe { .. } | FfiUnsafeWrapper { .. } ) => return r,
10011014 }
10021015 }
10031016
@@ -1278,8 +1291,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12781291 & mut self ,
12791292 ty : Ty < ' tcx > ,
12801293 sp : Span ,
1281- note : DiagMessage ,
1282- help : Option < DiagMessage > ,
1294+ mut reasons : Vec < ImproperCTypesLayer < ' tcx > > ,
12831295 ) {
12841296 let lint = match self . mode {
12851297 CItemKind :: Declaration => IMPROPER_CTYPES ,
@@ -1289,21 +1301,17 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12891301 CItemKind :: Declaration => "block" ,
12901302 CItemKind :: Definition => "fn" ,
12911303 } ;
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 } ) ;
13071315 }
13081316
13091317 fn check_for_opaque_ty ( & mut self , sp : Span , ty : Ty < ' tcx > ) -> bool {
@@ -1332,7 +1340,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13321340 . visit_with ( & mut ProhibitOpaqueTypes )
13331341 . break_value ( )
13341342 {
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+ } ] ) ;
13361350 true
13371351 } else {
13381352 false
@@ -1371,15 +1385,75 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13711385 match self . check_type_for_ffi ( & mut acc, ty) {
13721386 FfiResult :: FfiSafe => { }
13731387 FfiResult :: FfiPhantom ( ty) => {
1374- self . emit_ffi_unsafe_type_lint (
1388+ self . emit_ffi_unsafe_type_lint ( ty . clone ( ) , sp , vec ! [ ImproperCTypesLayer {
13751389 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+ } ] ) ;
13801395 }
13811396 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) ;
13831457 }
13841458 }
13851459 }
0 commit comments