@@ -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