@@ -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 , 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 } ;
@@ -556,25 +556,26 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
556
556
_ => false ,
557
557
}
558
558
}
559
- /// Given a potentially non-null type `ty`, return its default, nullable type.
560
- fn get_nullable_type < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> Ty < ' tcx > {
561
- match ty. kind {
559
+ /// Given a non-null scalar (or transparent) type `ty`, return the nullable version of that type.
560
+ /// If the type passed in was not scalar, returns None.
561
+ fn get_nullable_type < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > ) -> Option < Ty < ' tcx > > {
562
+ let tcx = cx. tcx ;
563
+ Some ( match ty. kind {
562
564
ty:: Adt ( field_def, field_substs) => {
563
- let field_variants = & field_def. variants ;
564
- // We hit this case for #[repr(transparent)] structs with a single
565
- // field.
566
- debug_assert ! (
567
- field_variants. len( ) == 1 && field_variants[ VariantIdx :: new( 0 ) ] . fields. len( ) == 1 ,
568
- "inner ty not a newtype struct"
569
- ) ;
570
- debug_assert ! ( field_def. repr. transparent( ) , "inner ty not transparent" ) ;
571
- // As it's easy to get this wrong, it's worth noting that
572
- // `inner_field_ty` is not the same as `field_ty`: Given Option<S>,
573
- // where S is a transparent newtype of some type T, `field_ty`
574
- // gives us S, while `inner_field_ty` is T.
575
- let inner_field_ty =
576
- field_def. variants [ VariantIdx :: new ( 0 ) ] . fields [ 0 ] . ty ( tcx, field_substs) ;
577
- get_nullable_type ( tcx, inner_field_ty)
565
+ let inner_field_ty = {
566
+ let first_non_zst_ty =
567
+ field_def. variants . iter ( ) . filter_map ( |v| v. transparent_newtype_field ( tcx) ) ;
568
+ debug_assert_eq ! (
569
+ first_non_zst_ty. clone( ) . count( ) ,
570
+ 1 ,
571
+ "Wrong number of fields for transparent type"
572
+ ) ;
573
+ first_non_zst_ty
574
+ . last ( )
575
+ . expect ( "No non-zst fields in transparent type." )
576
+ . ty ( tcx, field_substs)
577
+ } ;
578
+ return get_nullable_type ( cx, inner_field_ty) ;
578
579
}
579
580
ty:: Int ( ty) => tcx. mk_mach_int ( ty) ,
580
581
ty:: Uint ( ty) => tcx. mk_mach_uint ( ty) ,
@@ -591,9 +592,13 @@ fn get_nullable_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
591
592
// We should only ever reach this case if ty_is_known_nonnull is extended
592
593
// to other types.
593
594
ref unhandled => {
594
- unreachable ! ( "Unhandled scalar kind: {:?} while checking {:?}" , unhandled, ty)
595
+ debug ! (
596
+ "get_nullable_type: Unhandled scalar kind: {:?} while checking {:?}" ,
597
+ unhandled, ty
598
+ ) ;
599
+ return None ;
595
600
}
596
- }
601
+ } )
597
602
}
598
603
599
604
/// Check if this enum can be safely exported based on the "nullable pointer optimization". If it
@@ -643,9 +648,9 @@ crate fn repr_nullable_ptr<'tcx>(
643
648
let field_ty_abi = & cx. layout_of ( field_ty) . unwrap ( ) . abi ;
644
649
if let Abi :: Scalar ( field_ty_scalar) = field_ty_abi {
645
650
match ( field_ty_scalar. valid_range . start ( ) , field_ty_scalar. valid_range . end ( ) ) {
646
- ( 0 , _) => bug ! ( "Non-null optimisation extended to a non-zero value." ) ,
651
+ ( 0 , _) => unreachable ! ( "Non-null optimisation extended to a non-zero value." ) ,
647
652
( 1 , _) => {
648
- return Some ( get_nullable_type ( cx. tcx , field_ty) ) ;
653
+ return Some ( get_nullable_type ( cx, field_ty) . unwrap ( ) ) ;
649
654
}
650
655
( start, end) => unreachable ! ( "Unhandled start and end range: ({}, {})" , start, end) ,
651
656
} ;
0 commit comments