@@ -3,6 +3,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
33use crate :: query:: TyCtxtAt ;
44use crate :: ty:: normalize_erasing_regions:: NormalizationError ;
55use crate :: ty:: { self , Ty , TyCtxt , TypeVisitableExt } ;
6+ use hir:: Mutability ;
67use rustc_error_messages:: DiagMessage ;
78use rustc_errors:: {
89 Diag , DiagArgValue , DiagCtxt , Diagnostic , EmissionGuarantee , IntoDiagArg , Level ,
@@ -319,6 +320,8 @@ pub enum SizeSkeleton<'tcx> {
319320 Pointer {
320321 /// If true, this pointer is never null.
321322 non_zero : bool ,
323+ /// Available if the width of the pointer is known, i.e. whether it's 1 or 2 usizes
324+ known_size : Option < Size > ,
322325 /// The type which determines the unsized metadata, if any,
323326 /// of this pointer. Either a type parameter or a projection
324327 /// depending on one, with regions erased.
@@ -372,7 +375,23 @@ impl<'tcx> SizeSkeleton<'tcx> {
372375 match tail. kind ( ) {
373376 ty:: Param ( _) | ty:: Alias ( ty:: Projection | ty:: Inherent , _) => {
374377 debug_assert ! ( tail. has_non_region_param( ) ) ;
375- Ok ( SizeSkeleton :: Pointer { non_zero, tail : tcx. erase_regions ( tail) } )
378+ Ok ( SizeSkeleton :: Pointer {
379+ non_zero,
380+ known_size : None ,
381+ tail : tcx. erase_regions ( tail) ,
382+ } )
383+ }
384+ ty:: Slice ( _) => {
385+ debug_assert ! ( tail. has_non_region_param( ) ) ;
386+ // Assumption: all slice pointers have the same size. At most they differ in niches or or ptr/len ordering
387+ let simple_slice =
388+ Ty :: new_ptr ( tcx, Ty :: new_slice ( tcx, tcx. types . unit ) , Mutability :: Not ) ;
389+ let size = tcx. layout_of ( param_env. and ( simple_slice) ) . unwrap ( ) . size ;
390+ Ok ( SizeSkeleton :: Pointer {
391+ non_zero,
392+ known_size : Some ( size) ,
393+ tail : tcx. erase_regions ( tail) ,
394+ } )
376395 }
377396 ty:: Error ( guar) => {
378397 // Fixes ICE #124031
@@ -449,7 +468,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
449468 let v0 = zero_or_ptr_variant ( 0 ) ?;
450469 // Newtype.
451470 if def. variants ( ) . len ( ) == 1 {
452- if let Some ( SizeSkeleton :: Pointer { non_zero, tail } ) = v0 {
471+ if let Some ( SizeSkeleton :: Pointer { non_zero, known_size , tail } ) = v0 {
453472 return Ok ( SizeSkeleton :: Pointer {
454473 non_zero : non_zero
455474 || match tcx. layout_scalar_valid_range ( def. did ( ) ) {
@@ -459,6 +478,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
459478 }
460479 _ => false ,
461480 } ,
481+ known_size,
462482 tail,
463483 } ) ;
464484 } else {
@@ -469,9 +489,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
469489 let v1 = zero_or_ptr_variant ( 1 ) ?;
470490 // Nullable pointer enum optimization.
471491 match ( v0, v1) {
472- ( Some ( SizeSkeleton :: Pointer { non_zero : true , tail } ) , None )
473- | ( None , Some ( SizeSkeleton :: Pointer { non_zero : true , tail } ) ) => {
474- Ok ( SizeSkeleton :: Pointer { non_zero : false , tail } )
492+ ( Some ( SizeSkeleton :: Pointer { non_zero : true , known_size , tail } ) , None )
493+ | ( None , Some ( SizeSkeleton :: Pointer { non_zero : true , known_size , tail } ) ) => {
494+ Ok ( SizeSkeleton :: Pointer { non_zero : false , known_size , tail } )
475495 }
476496 _ => Err ( err) ,
477497 }
@@ -492,7 +512,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
492512
493513 pub fn same_size ( self , other : SizeSkeleton < ' tcx > ) -> bool {
494514 match ( self , other) {
495- ( SizeSkeleton :: Known ( a) , SizeSkeleton :: Known ( b) ) => a == b,
515+ (
516+ SizeSkeleton :: Known ( a) | SizeSkeleton :: Pointer { known_size : Some ( a) , .. } ,
517+ SizeSkeleton :: Known ( b) | SizeSkeleton :: Pointer { known_size : Some ( b) , .. } ,
518+ ) => a == b,
496519 ( SizeSkeleton :: Pointer { tail : a, .. } , SizeSkeleton :: Pointer { tail : b, .. } ) => {
497520 a == b
498521 }
0 commit comments