@@ -1384,35 +1384,40 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1384
1384
/// Argument types and the result type are checked for functions with external ABIs.
1385
1385
/// For functions with internal ABIs, argument types and the result type are walked to find
1386
1386
/// fn-ptr types that have external ABIs, as these still need checked.
1387
- fn check_maybe_foreign_fn ( & mut self , abi : SpecAbi , def_id : LocalDefId , decl : & hir:: FnDecl < ' _ > ) {
1387
+ fn check_maybe_foreign_fn (
1388
+ & mut self ,
1389
+ abi : SpecAbi ,
1390
+ def_id : LocalDefId ,
1391
+ decl : & ' tcx hir:: FnDecl < ' _ > ,
1392
+ ) {
1388
1393
let sig = self . cx . tcx . fn_sig ( def_id) . subst_identity ( ) ;
1389
1394
let sig = self . cx . tcx . erase_late_bound_regions ( sig) ;
1390
1395
1391
1396
let is_internal_abi = self . is_internal_abi ( abi) ;
1392
1397
let check_ty = |this : & mut ImproperCTypesVisitor < ' a , ' tcx > ,
1393
- span : Span ,
1398
+ hir_ty : & ' tcx hir :: Ty < ' _ > ,
1394
1399
ty : Ty < ' tcx > ,
1395
1400
is_return_type : bool | {
1396
1401
// If this function has an external ABI, then its arguments and return type should be
1397
1402
// checked..
1398
1403
if !is_internal_abi {
1399
- this. check_type_for_ffi_and_report_errors ( span, ty, false , is_return_type) ;
1404
+ this. check_type_for_ffi_and_report_errors ( hir_ty . span , ty, false , is_return_type) ;
1400
1405
return ;
1401
1406
}
1402
1407
1403
1408
// ..but if this function has an internal ABI, then search the argument or return type
1404
1409
// for any fn-ptr types with external ABI, which should be checked..
1405
- if let Some ( fn_ptr_ty) = this. find_fn_ptr_ty_with_external_abi ( ty) {
1410
+ for ( fn_ptr_ty, span ) in this. find_fn_ptr_ty_with_external_abi ( hir_ty , ty) {
1406
1411
this. check_type_for_ffi_and_report_errors ( span, fn_ptr_ty, false , is_return_type) ;
1407
1412
}
1408
1413
} ;
1409
1414
1410
1415
for ( input_ty, input_hir) in iter:: zip ( sig. inputs ( ) , decl. inputs ) {
1411
- check_ty ( self , input_hir. span , * input_ty, false ) ;
1416
+ check_ty ( self , input_hir, * input_ty, false ) ;
1412
1417
}
1413
1418
1414
1419
if let hir:: FnRetTy :: Return ( ref ret_hir) = decl. output {
1415
- check_ty ( self , ret_hir. span , sig. output ( ) , true ) ;
1420
+ check_ty ( self , ret_hir, sig. output ( ) , true ) ;
1416
1421
}
1417
1422
}
1418
1423
@@ -1431,30 +1436,52 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
1431
1436
/// Find any fn-ptr types with external ABIs in `ty`.
1432
1437
///
1433
1438
/// For example, `Option<extern "C" fn()>` returns `extern "C" fn()`
1434
- fn find_fn_ptr_ty_with_external_abi ( & self , ty : Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
1435
- struct FnPtrFinder < ' parent , ' a , ' tcx > ( & ' parent ImproperCTypesVisitor < ' a , ' tcx > ) ;
1439
+ fn find_fn_ptr_ty_with_external_abi (
1440
+ & self ,
1441
+ hir_ty : & hir:: Ty < ' tcx > ,
1442
+ ty : Ty < ' tcx > ,
1443
+ ) -> Vec < ( Ty < ' tcx > , Span ) > {
1444
+ struct FnPtrFinder < ' parent , ' a , ' tcx > {
1445
+ visitor : & ' parent ImproperCTypesVisitor < ' a , ' tcx > ,
1446
+ spans : Vec < Span > ,
1447
+ tys : Vec < Ty < ' tcx > > ,
1448
+ }
1449
+
1450
+ impl < ' parent , ' a , ' tcx > hir:: intravisit:: Visitor < ' _ > for FnPtrFinder < ' parent , ' a , ' tcx > {
1451
+ fn visit_ty ( & mut self , ty : & ' _ hir:: Ty < ' _ > ) {
1452
+ debug ! ( ?ty) ;
1453
+ if let hir:: TyKind :: BareFn ( hir:: BareFnTy { abi, .. } ) = ty. kind
1454
+ && !self . visitor . is_internal_abi ( * abi)
1455
+ {
1456
+ self . spans . push ( ty. span ) ;
1457
+ }
1458
+
1459
+ hir:: intravisit:: walk_ty ( self , ty)
1460
+ }
1461
+ }
1462
+
1436
1463
impl < ' vis , ' a , ' tcx > ty:: visit:: TypeVisitor < TyCtxt < ' tcx > > for FnPtrFinder < ' vis , ' a , ' tcx > {
1437
1464
type BreakTy = Ty < ' tcx > ;
1438
1465
1439
1466
fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
1440
- if let ty:: FnPtr ( sig) = ty. kind ( ) && !self . 0 . is_internal_abi ( sig. abi ( ) ) {
1441
- ControlFlow :: Break ( ty)
1442
- } else {
1443
- ty. super_visit_with ( self )
1467
+ if let ty:: FnPtr ( sig) = ty. kind ( ) && !self . visitor . is_internal_abi ( sig. abi ( ) ) {
1468
+ self . tys . push ( ty) ;
1444
1469
}
1470
+
1471
+ ty. super_visit_with ( self )
1445
1472
}
1446
1473
}
1447
1474
1448
- self . cx
1449
- . tcx
1450
- . normalize_erasing_regions ( self . cx . param_env , ty )
1451
- . visit_with ( & mut FnPtrFinder ( & * self ) )
1452
- . break_value ( )
1475
+ let mut visitor = FnPtrFinder { visitor : & * self , spans : Vec :: new ( ) , tys : Vec :: new ( ) } ;
1476
+ self . cx . tcx . normalize_erasing_regions ( self . cx . param_env , ty ) . visit_with ( & mut visitor ) ;
1477
+ hir :: intravisit :: Visitor :: visit_ty ( & mut visitor , hir_ty ) ;
1478
+
1479
+ iter :: zip ( visitor . tys . drain ( .. ) , visitor . spans . drain ( .. ) ) . collect ( )
1453
1480
}
1454
1481
}
1455
1482
1456
1483
impl < ' tcx > LateLintPass < ' tcx > for ImproperCTypesDeclarations {
1457
- fn check_foreign_item ( & mut self , cx : & LateContext < ' _ > , it : & hir:: ForeignItem < ' _ > ) {
1484
+ fn check_foreign_item ( & mut self , cx : & LateContext < ' tcx > , it : & hir:: ForeignItem < ' tcx > ) {
1458
1485
let mut vis = ImproperCTypesVisitor { cx, mode : CItemKind :: Declaration } ;
1459
1486
let abi = cx. tcx . hir ( ) . get_foreign_abi ( it. hir_id ( ) ) ;
1460
1487
0 commit comments