@@ -11,7 +11,7 @@ use rustc_index::vec::Idx;
1111use  rustc_middle:: mir:: interpret:: { sign_extend,  truncate} ; 
1212use  rustc_middle:: ty:: layout:: { IntegerExt ,  SizeSkeleton } ; 
1313use  rustc_middle:: ty:: subst:: SubstsRef ; 
14- use  rustc_middle:: ty:: { self ,  AdtKind ,  ParamEnv ,   Ty ,   TyCtxt ,  TypeFoldable } ; 
14+ use  rustc_middle:: ty:: { self ,  AdtKind ,  Ty ,  TypeFoldable } ; 
1515use  rustc_span:: source_map; 
1616use  rustc_span:: symbol:: sym; 
1717use  rustc_span:: { Span ,  DUMMY_SP } ; 
@@ -525,78 +525,82 @@ enum FfiResult<'tcx> {
525525    FfiUnsafe  {  ty :  Ty < ' tcx > ,  reason :  String ,  help :  Option < String >  } , 
526526} 
527527
528- fn  ty_is_known_nonnull < ' tcx > ( tcx :  TyCtxt < ' tcx > ,  ty :  Ty < ' tcx > )  -> bool  { 
529-     match  ty. kind  { 
530-         ty:: FnPtr ( _)  => true , 
531-         ty:: Ref ( ..)  => true , 
532-         ty:: Adt ( field_def,  substs)  if  field_def. repr . transparent ( )  && !field_def. is_union ( )  => { 
533-             for  field in  field_def. all_fields ( )  { 
534-                 let  field_ty =
535-                     tcx. normalize_erasing_regions ( ParamEnv :: reveal_all ( ) ,  field. ty ( tcx,  substs) ) ; 
536-                 if  field_ty. is_zst ( tcx,  field. did )  { 
537-                     continue ; 
538-                 } 
528+ impl < ' a ,  ' tcx >  ImproperCTypesVisitor < ' a ,  ' tcx >  { 
529+     /// Is type known to be non-null? 
530+ fn  ty_is_known_nonnull ( & self ,  ty :  Ty < ' tcx > )  -> bool  { 
531+         match  ty. kind  { 
532+             ty:: FnPtr ( _)  => true , 
533+             ty:: Ref ( ..)  => true , 
534+             ty:: Adt ( field_def,  substs)  if  field_def. repr . transparent ( )  && !field_def. is_union ( )  => { 
535+                 for  field in  field_def. all_fields ( )  { 
536+                     let  field_ty = self . cx . tcx . normalize_erasing_regions ( 
537+                         self . cx . param_env , 
538+                         field. ty ( self . cx . tcx ,  substs) , 
539+                     ) ; 
540+                     if  field_ty. is_zst ( self . cx . tcx ,  field. did )  { 
541+                         continue ; 
542+                     } 
539543
540-                 let  attrs = tcx. get_attrs ( field_def. did ) ; 
541-                 if  attrs. iter ( ) . any ( |a| a. check_name ( sym:: rustc_nonnull_optimization_guaranteed) ) 
542-                     || ty_is_known_nonnull ( tcx,  field_ty) 
543-                 { 
544-                     return  true ; 
544+                     let  attrs = self . cx . tcx . get_attrs ( field_def. did ) ; 
545+                     if  attrs
546+                         . iter ( ) 
547+                         . any ( |a| a. check_name ( sym:: rustc_nonnull_optimization_guaranteed) ) 
548+                         || self . ty_is_known_nonnull ( field_ty) 
549+                     { 
550+                         return  true ; 
551+                     } 
545552                } 
546-             } 
547553
548-             false 
554+                 false 
555+             } 
556+             _ => false , 
549557        } 
550-         _ => false , 
551558    } 
552- } 
553559
554- /// Check if this enum can be safely exported based on the 
555- /// "nullable pointer optimization". Currently restricted 
556- /// to function pointers, references, core::num::NonZero*, 
557- /// core::ptr::NonNull, and #[repr(transparent)] newtypes. 
558- /// FIXME: This duplicates code in codegen. 
559- fn  is_repr_nullable_ptr < ' tcx > ( 
560-     tcx :  TyCtxt < ' tcx > , 
561-     ty :  Ty < ' tcx > , 
562-     ty_def :  & ' tcx  ty:: AdtDef , 
563-     substs :  SubstsRef < ' tcx > , 
564- )  -> bool  { 
565-     if  ty_def. variants . len ( )  != 2  { 
566-         return  false ; 
567-     } 
560+     /// Check if this enum can be safely exported based on the "nullable pointer optimization". 
561+ /// Currently restricted to function pointers, references, `core::num::NonZero*`, 
562+ /// `core::ptr::NonNull`, and `#[repr(transparent)]` newtypes. 
563+ fn  is_repr_nullable_ptr ( 
564+         & self , 
565+         ty :  Ty < ' tcx > , 
566+         ty_def :  & ' tcx  ty:: AdtDef , 
567+         substs :  SubstsRef < ' tcx > , 
568+     )  -> bool  { 
569+         if  ty_def. variants . len ( )  != 2  { 
570+             return  false ; 
571+         } 
568572
569-     let  get_variant_fields = |index| & ty_def. variants [ VariantIdx :: new ( index) ] . fields ; 
570-     let  variant_fields = [ get_variant_fields ( 0 ) ,  get_variant_fields ( 1 ) ] ; 
571-     let  fields = if  variant_fields[ 0 ] . is_empty ( )  { 
572-         & variant_fields[ 1 ] 
573-     }  else  if  variant_fields[ 1 ] . is_empty ( )  { 
574-         & variant_fields[ 0 ] 
575-     }  else  { 
576-         return  false ; 
577-     } ; 
573+          let  get_variant_fields = |index| & ty_def. variants [ VariantIdx :: new ( index) ] . fields ; 
574+          let  variant_fields = [ get_variant_fields ( 0 ) ,  get_variant_fields ( 1 ) ] ; 
575+          let  fields = if  variant_fields[ 0 ] . is_empty ( )  { 
576+              & variant_fields[ 1 ] 
577+          }  else  if  variant_fields[ 1 ] . is_empty ( )  { 
578+              & variant_fields[ 0 ] 
579+          }  else  { 
580+              return  false ; 
581+          } ; 
578582
579-     if  fields. len ( )  != 1  { 
580-         return  false ; 
581-     } 
583+          if  fields. len ( )  != 1  { 
584+              return  false ; 
585+          } 
582586
583-     let  field_ty = fields[ 0 ] . ty ( tcx,  substs) ; 
584-     if  !ty_is_known_nonnull ( tcx ,   field_ty)  { 
585-         return  false ; 
586-     } 
587+          let  field_ty = fields[ 0 ] . ty ( self . cx . tcx ,  substs) ; 
588+          if  !self . ty_is_known_nonnull ( field_ty)  { 
589+              return  false ; 
590+          } 
587591
588-     // At this point, the field's type is known to be nonnull and the parent enum is Option-like. 
589-     // If the computed size for the field and the enum are different, the nonnull optimization isn't 
590-     // being applied (and we've got a problem somewhere). 
591-     let  compute_size_skeleton = |t| SizeSkeleton :: compute ( t,  tcx,  ParamEnv :: reveal_all ( ) ) . unwrap ( ) ; 
592-     if  !compute_size_skeleton ( ty) . same_size ( compute_size_skeleton ( field_ty) )  { 
593-         bug ! ( "improper_ctypes: Option nonnull optimization not applied?" ) ; 
594-     } 
592+         // At this point, the field's type is known to be nonnull and the parent enum is 
593+         // Option-like. If the computed size for the field and the enum are different, the non-null 
594+         // optimization isn't being applied (and we've got a problem somewhere). 
595+         let  compute_size_skeleton =
596+             |t| SizeSkeleton :: compute ( t,  self . cx . tcx ,  self . cx . param_env ) . unwrap ( ) ; 
597+         if  !compute_size_skeleton ( ty) . same_size ( compute_size_skeleton ( field_ty) )  { 
598+             bug ! ( "improper_ctypes: Option nonnull optimization not applied?" ) ; 
599+         } 
595600
596-     true 
597- } 
601+          true 
602+      } 
598603
599- impl < ' a ,  ' tcx >  ImproperCTypesVisitor < ' a ,  ' tcx >  { 
600604    /// Check if the type is array and emit an unsafe type lint. 
601605fn  check_for_array_ty ( & mut  self ,  sp :  Span ,  ty :  Ty < ' tcx > )  -> bool  { 
602606        if  let  ty:: Array ( ..)  = ty. kind  { 
@@ -738,7 +742,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
738742                        // discriminant. 
739743                        if  !def. repr . c ( )  && !def. repr . transparent ( )  && def. repr . int . is_none ( )  { 
740744                            // Special-case types like `Option<extern fn()>`. 
741-                             if  !is_repr_nullable_ptr ( cx ,   ty,  def,  substs)  { 
745+                             if  !self . is_repr_nullable_ptr ( ty,  def,  substs)  { 
742746                                return  FfiUnsafe  { 
743747                                    ty, 
744748                                    reason :  "enum has no representation hint" . into ( ) , 
0 commit comments