@@ -3,7 +3,6 @@ use std::ops::ControlFlow;
33
44use rustc_data_structures:: fx:: FxHashSet ;
55use rustc_errors:: DiagMessage ;
6- use rustc_hir:: def:: CtorKind ;
76use rustc_hir:: { is_range_literal, Expr , ExprKind , Node } ;
87use rustc_middle:: bug;
98use rustc_middle:: ty:: layout:: { IntegerExt , LayoutOf , SizeSkeleton } ;
@@ -19,6 +18,8 @@ use rustc_target::spec::abi::Abi as SpecAbi;
1918use tracing:: debug;
2019use { rustc_ast as ast, rustc_attr as attr, rustc_hir as hir} ;
2120
21+ mod improper_ctypes;
22+
2223use crate :: lints:: {
2324 AmbiguousWidePointerComparisons , AmbiguousWidePointerComparisonsAddrMetadataSuggestion ,
2425 AmbiguousWidePointerComparisonsAddrSuggestion , AtomicOrderingFence , AtomicOrderingLoad ,
@@ -1405,38 +1406,23 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
14051406 } ;
14061407 }
14071408
1408- // non_exhaustive suggests it is possible that someone might break ABI
1409- // see: https://github.com/rust-lang/rust/issues/44109#issuecomment-537583344
1410- // so warn on complex enums being used outside their crate
1411- let nonexhaustive_nonlocal_ffi =
1412- def. is_variant_list_non_exhaustive ( ) && !def. did ( ) . is_local ( ) ;
1409+ use improper_ctypes:: {
1410+ check_non_exhaustive_variant, non_local_and_non_exhaustive,
1411+ } ;
14131412
1413+ let non_local_def = non_local_and_non_exhaustive ( def) ;
14141414 // Check the contained variants.
1415- for variant in def. variants ( ) {
1416- // but only warn about really_tagged_union reprs,
1417- // exempt enums with unit ctors like C's (like rust-bindgen)
1418- if nonexhaustive_nonlocal_ffi
1419- && !matches ! ( variant. ctor_kind( ) , Some ( CtorKind :: Const ) )
1420- {
1421- return FfiUnsafe {
1422- ty,
1423- reason : fluent:: lint_improper_ctypes_non_exhaustive,
1424- help : None ,
1425- } ;
1426- } ;
1427- let is_non_exhaustive = variant. is_field_list_non_exhaustive ( ) ;
1428- if is_non_exhaustive && !variant. def_id . is_local ( ) {
1429- return FfiUnsafe {
1430- ty,
1431- reason : fluent:: lint_improper_ctypes_non_exhaustive_variant,
1432- help : None ,
1433- } ;
1434- }
1415+ let ret = def. variants ( ) . iter ( ) . try_for_each ( |variant| {
1416+ check_non_exhaustive_variant ( non_local_def, variant)
1417+ . map_break ( |reason| FfiUnsafe { ty, reason, help : None } ) ?;
14351418
14361419 match self . check_variant_for_ffi ( acc, ty, def, variant, args) {
1437- FfiSafe => ( ) ,
1438- r => return r ,
1420+ FfiSafe => ControlFlow :: Continue ( ( ) ) ,
1421+ r => ControlFlow :: Break ( r ) ,
14391422 }
1423+ } ) ;
1424+ if let ControlFlow :: Break ( result) = ret {
1425+ return result;
14401426 }
14411427
14421428 FfiSafe
0 commit comments