@@ -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 , 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 } ;
@@ -556,25 +556,26 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
556556 _ => false ,
557557 }
558558}
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 {
562564 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) ;
578579 }
579580 ty:: Int ( ty) => tcx. mk_mach_int ( ty) ,
580581 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> {
591592 // We should only ever reach this case if ty_is_known_nonnull is extended
592593 // to other types.
593594 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 ;
595600 }
596- }
601+ } )
597602}
598603
599604/// 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>(
643648 let field_ty_abi = & cx. layout_of ( field_ty) . unwrap ( ) . abi ;
644649 if let Abi :: Scalar ( field_ty_scalar) = field_ty_abi {
645650 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." ) ,
647652 ( 1 , _) => {
648- return Some ( get_nullable_type ( cx. tcx , field_ty) ) ;
653+ return Some ( get_nullable_type ( cx, field_ty) . unwrap ( ) ) ;
649654 }
650655 ( start, end) => unreachable ! ( "Unhandled start and end range: ({}, {})" , start, end) ,
651656 } ;
0 commit comments