@@ -659,9 +659,6 @@ bitflags! {
659659 /// To show that there is no outer type, the current type is directly used by a `static`
660660 /// variable or a function/FnPtr
661661 const NO_OUTER_TY = 0b100000 ;
662- /// For NO_OUTER_TY cases, show that we are being directly used by a FnPtr specifically
663- /// FIXME(ctypes): this is only used for "bad behaviour" reproduced for compatibility's sake
664- const NOOUT_FNPTR = 0b1000000 ;
665662 }
666663}
667664
@@ -696,7 +693,7 @@ impl EphemeralStateFlags {
696693 /// modify self to change the ephemeral part of the flags
697694 fn from_outer_ty < ' tcx > ( ty : Ty < ' tcx > ) -> Self {
698695 match ty. kind ( ) {
699- ty:: FnPtr ( ..) => Self :: NO_OUTER_TY | Self :: NOOUT_FNPTR ,
696+ ty:: FnPtr ( ..) => Self :: NO_OUTER_TY ,
700697 k @ ( ty:: RawPtr ( ..) | ty:: Ref ( ..) ) => {
701698 let mut ret = Self :: IN_PTR ;
702699 if ty. is_mutable_ptr ( ) {
@@ -740,7 +737,7 @@ impl VisitorState {
740737 } else {
741738 PersistentStateFlags :: ARGUMENT_TY_IN_FNPTR
742739 } ,
743- ephemeral_flags : EphemeralStateFlags :: NO_OUTER_TY | EphemeralStateFlags :: NOOUT_FNPTR ,
740+ ephemeral_flags : EphemeralStateFlags :: NO_OUTER_TY ,
744741 }
745742 }
746743
@@ -779,6 +776,15 @@ impl VisitorState {
779776 Self :: entry_point ( PersistentStateFlags :: STATIC_TY )
780777 }
781778
779+ /// Whether the type is used as the type of a static variable.
780+ fn is_direct_in_static ( & self ) -> bool {
781+ let ret = self . persistent_flags . contains ( PersistentStateFlags :: STATIC ) ;
782+ if ret {
783+ debug_assert ! ( !self . persistent_flags. contains( PersistentStateFlags :: FUNC ) ) ;
784+ }
785+ ret && self . ephemeral_flags . contains ( EphemeralStateFlags :: NO_OUTER_TY )
786+ }
787+
782788 /// Whether the type is used in a function.
783789 fn is_in_function ( & self ) -> bool {
784790 let ret = self . persistent_flags . contains ( PersistentStateFlags :: FUNC ) ;
@@ -844,6 +850,12 @@ impl VisitorState {
844850 fn is_raw_pointee ( & self ) -> bool {
845851 self . ephemeral_flags . contains ( EphemeralStateFlags :: IN_PTR | EphemeralStateFlags :: PTR_RAW )
846852 }
853+
854+ /// Whether the current type directly in the memory layout of the parent ty
855+ #[ inline]
856+ fn is_memory_inlined ( & self ) -> bool {
857+ self . ephemeral_flags . contains ( EphemeralStateFlags :: MEMORY_INLINED )
858+ }
847859}
848860
849861/// Visitor used to recursively traverse MIR types and evaluate FFI-safety.
@@ -1320,11 +1332,21 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13201332 Some ( fluent:: lint_improper_ctypes_char_help) ,
13211333 ) ,
13221334
1323- ty:: Slice ( _) => FfiResult :: new_with_reason (
1324- ty,
1325- fluent:: lint_improper_ctypes_slice_reason,
1326- Some ( fluent:: lint_improper_ctypes_slice_help) ,
1327- ) ,
1335+ ty:: Slice ( inner_ty) => {
1336+ // ty::Slice is used for !Sized arrays, since they are the pointee for actual slices
1337+ let slice_is_actually_array =
1338+ state. is_memory_inlined ( ) || state. is_direct_in_static ( ) ;
1339+
1340+ if slice_is_actually_array {
1341+ self . visit_type ( state. get_next ( ty) , inner_ty)
1342+ } else {
1343+ FfiResult :: new_with_reason (
1344+ ty,
1345+ fluent:: lint_improper_ctypes_slice_reason,
1346+ Some ( fluent:: lint_improper_ctypes_slice_help) ,
1347+ )
1348+ }
1349+ }
13281350
13291351 ty:: Dynamic ( ..) => {
13301352 FfiResult :: new_with_reason ( ty, fluent:: lint_improper_ctypes_dyn, None )
@@ -1376,10 +1398,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
13761398 }
13771399
13781400 ty:: Array ( inner_ty, _) => {
1379- if state. is_direct_in_function ( )
1380- // FIXME(ctypes): VVV-this-VVV shouldn't be the case
1381- && !state. ephemeral_flags . contains ( EphemeralStateFlags :: NOOUT_FNPTR )
1382- {
1401+ if state. is_direct_in_function ( ) {
13831402 // C doesn't really support passing arrays by value - the only way to pass an array by value
13841403 // is through a struct.
13851404 FfiResult :: new_with_reason (
0 commit comments