@@ -946,7 +946,13 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
946946 }
947947 }
948948
949- fn check_type_for_ffi_and_report_errors ( & mut self , sp : Span , ty : Ty < ' tcx > , is_static : bool ) {
949+ fn check_type_for_ffi_and_report_errors (
950+ & mut self ,
951+ sp : Span ,
952+ ty : Ty < ' tcx > ,
953+ is_static : bool ,
954+ is_return_type : bool ,
955+ ) {
950956 // We have to check for opaque types before `normalize_erasing_regions`,
951957 // which will replace opaque types with their underlying concrete type.
952958 if self . check_for_opaque_ty ( sp, ty) {
@@ -957,14 +963,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
957963 // it is only OK to use this function because extern fns cannot have
958964 // any generic types right now:
959965 let ty = self . cx . tcx . normalize_erasing_regions ( ParamEnv :: reveal_all ( ) , ty) ;
960- // C doesn't really support passing arrays by value.
961- // The only way to pass an array by value is through a struct.
962- // So we first test that the top level isn't an array,
963- // and then recursively check the types inside.
966+
967+ // C doesn't really support passing arrays by value - the only way to pass an array by value
968+ // is through a struct. So, first test that the top level isn't an array, and then
969+ // recursively check the types inside.
964970 if !is_static && self . check_for_array_ty ( sp, ty) {
965971 return ;
966972 }
967973
974+ // Don't report FFI errors for unit return types. This check exists here, and not in
975+ // `check_foreign_fn` (where it would make more sense) so that normalization has definitely
976+ // happened.
977+ if is_return_type && ty. is_unit ( ) {
978+ return ;
979+ }
980+
968981 match self . check_type_for_ffi ( & mut FxHashSet :: default ( ) , ty) {
969982 FfiResult :: FfiSafe => { }
970983 FfiResult :: FfiPhantom ( ty) => {
@@ -982,21 +995,19 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
982995 let sig = self . cx . tcx . erase_late_bound_regions ( & sig) ;
983996
984997 for ( input_ty, input_hir) in sig. inputs ( ) . iter ( ) . zip ( decl. inputs ) {
985- self . check_type_for_ffi_and_report_errors ( input_hir. span , input_ty, false ) ;
998+ self . check_type_for_ffi_and_report_errors ( input_hir. span , input_ty, false , false ) ;
986999 }
9871000
9881001 if let hir:: FnRetTy :: Return ( ref ret_hir) = decl. output {
9891002 let ret_ty = sig. output ( ) ;
990- if !ret_ty. is_unit ( ) {
991- self . check_type_for_ffi_and_report_errors ( ret_hir. span , ret_ty, false ) ;
992- }
1003+ self . check_type_for_ffi_and_report_errors ( ret_hir. span , ret_ty, false , true ) ;
9931004 }
9941005 }
9951006
9961007 fn check_foreign_static ( & mut self , id : hir:: HirId , span : Span ) {
9971008 let def_id = self . cx . tcx . hir ( ) . local_def_id ( id) ;
9981009 let ty = self . cx . tcx . type_of ( def_id) ;
999- self . check_type_for_ffi_and_report_errors ( span, ty, true ) ;
1010+ self . check_type_for_ffi_and_report_errors ( span, ty, true , false ) ;
10001011 }
10011012}
10021013
0 commit comments