@@ -1235,35 +1235,40 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12351235 /// Argument types and the result type are checked for functions with external ABIs.
12361236 /// For functions with internal ABIs, argument types and the result type are walked to find
12371237 /// fn-ptr types that have external ABIs, as these still need checked.
1238- fn check_maybe_foreign_fn ( & mut self , abi : SpecAbi , def_id : LocalDefId , decl : & hir:: FnDecl < ' _ > ) {
1238+ fn check_maybe_foreign_fn (
1239+ & mut self ,
1240+ abi : SpecAbi ,
1241+ def_id : LocalDefId ,
1242+ decl : & ' tcx hir:: FnDecl < ' _ > ,
1243+ ) {
12391244 let sig = self . cx . tcx . fn_sig ( def_id) . subst_identity ( ) ;
12401245 let sig = self . cx . tcx . erase_late_bound_regions ( sig) ;
12411246
12421247 let is_internal_abi = self . is_internal_abi ( abi) ;
12431248 let check_ty = |this : & mut ImproperCTypesVisitor < ' a , ' tcx > ,
1244- span : Span ,
1249+ hir_ty : & ' tcx hir :: Ty < ' _ > ,
12451250 ty : Ty < ' tcx > ,
12461251 is_return_type : bool | {
12471252 // If this function has an external ABI, then its arguments and return type should be
12481253 // checked..
12491254 if !is_internal_abi {
1250- this. check_type_for_ffi_and_report_errors ( span, ty, false , is_return_type) ;
1255+ this. check_type_for_ffi_and_report_errors ( hir_ty . span , ty, false , is_return_type) ;
12511256 return ;
12521257 }
12531258
12541259 // ..but if this function has an internal ABI, then search the argument or return type
12551260 // for any fn-ptr types with external ABI, which should be checked..
1256- if let Some ( fn_ptr_ty) = this. find_fn_ptr_ty_with_external_abi ( ty) {
1261+ for ( fn_ptr_ty, span ) in this. find_fn_ptr_ty_with_external_abi ( hir_ty , ty) {
12571262 this. check_type_for_ffi_and_report_errors ( span, fn_ptr_ty, false , is_return_type) ;
12581263 }
12591264 } ;
12601265
12611266 for ( input_ty, input_hir) in iter:: zip ( sig. inputs ( ) , decl. inputs ) {
1262- check_ty ( self , input_hir. span , * input_ty, false ) ;
1267+ check_ty ( self , input_hir, * input_ty, false ) ;
12631268 }
12641269
12651270 if let hir:: FnRetTy :: Return ( ref ret_hir) = decl. output {
1266- check_ty ( self , ret_hir. span , sig. output ( ) , true ) ;
1271+ check_ty ( self , ret_hir, sig. output ( ) , true ) ;
12671272 }
12681273 }
12691274
@@ -1282,30 +1287,52 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
12821287 /// Find any fn-ptr types with external ABIs in `ty`.
12831288 ///
12841289 /// For example, `Option<extern "C" fn()>` returns `extern "C" fn()`
1285- fn find_fn_ptr_ty_with_external_abi ( & self , ty : Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
1286- struct FnPtrFinder < ' parent , ' a , ' tcx > ( & ' parent ImproperCTypesVisitor < ' a , ' tcx > ) ;
1290+ fn find_fn_ptr_ty_with_external_abi (
1291+ & self ,
1292+ hir_ty : & hir:: Ty < ' tcx > ,
1293+ ty : Ty < ' tcx > ,
1294+ ) -> Vec < ( Ty < ' tcx > , Span ) > {
1295+ struct FnPtrFinder < ' parent , ' a , ' tcx > {
1296+ visitor : & ' parent ImproperCTypesVisitor < ' a , ' tcx > ,
1297+ spans : Vec < Span > ,
1298+ tys : Vec < Ty < ' tcx > > ,
1299+ }
1300+
1301+ impl < ' parent , ' a , ' tcx > hir:: intravisit:: Visitor < ' _ > for FnPtrFinder < ' parent , ' a , ' tcx > {
1302+ fn visit_ty ( & mut self , ty : & ' _ hir:: Ty < ' _ > ) {
1303+ debug ! ( ?ty) ;
1304+ if let hir:: TyKind :: BareFn ( hir:: BareFnTy { abi, .. } ) = ty. kind
1305+ && !self . visitor . is_internal_abi ( * abi)
1306+ {
1307+ self . spans . push ( ty. span ) ;
1308+ }
1309+
1310+ hir:: intravisit:: walk_ty ( self , ty)
1311+ }
1312+ }
1313+
12871314 impl < ' vis , ' a , ' tcx > ty:: visit:: TypeVisitor < TyCtxt < ' tcx > > for FnPtrFinder < ' vis , ' a , ' tcx > {
12881315 type BreakTy = Ty < ' tcx > ;
12891316
12901317 fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
1291- if let ty:: FnPtr ( sig) = ty. kind ( ) && !self . 0 . is_internal_abi ( sig. abi ( ) ) {
1292- ControlFlow :: Break ( ty)
1293- } else {
1294- ty. super_visit_with ( self )
1318+ if let ty:: FnPtr ( sig) = ty. kind ( ) && !self . visitor . is_internal_abi ( sig. abi ( ) ) {
1319+ self . tys . push ( ty) ;
12951320 }
1321+
1322+ ty. super_visit_with ( self )
12961323 }
12971324 }
12981325
1299- self . cx
1300- . tcx
1301- . normalize_erasing_regions ( self . cx . param_env , ty )
1302- . visit_with ( & mut FnPtrFinder ( & * self ) )
1303- . break_value ( )
1326+ let mut visitor = FnPtrFinder { visitor : & * self , spans : Vec :: new ( ) , tys : Vec :: new ( ) } ;
1327+ self . cx . tcx . normalize_erasing_regions ( self . cx . param_env , ty ) . visit_with ( & mut visitor ) ;
1328+ hir :: intravisit :: Visitor :: visit_ty ( & mut visitor , hir_ty ) ;
1329+
1330+ iter :: zip ( visitor . tys . drain ( .. ) , visitor . spans . drain ( .. ) ) . collect ( )
13041331 }
13051332}
13061333
13071334impl < ' tcx > LateLintPass < ' tcx > for ImproperCTypesDeclarations {
1308- fn check_foreign_item ( & mut self , cx : & LateContext < ' _ > , it : & hir:: ForeignItem < ' _ > ) {
1335+ fn check_foreign_item ( & mut self , cx : & LateContext < ' tcx > , it : & hir:: ForeignItem < ' tcx > ) {
13091336 let mut vis = ImproperCTypesVisitor { cx, mode : CItemKind :: Declaration } ;
13101337 let abi = cx. tcx . hir ( ) . get_foreign_abi ( it. hir_id ( ) ) ;
13111338
0 commit comments