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