@@ -3,6 +3,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
3
3
use crate :: query:: TyCtxtAt ;
4
4
use crate :: ty:: normalize_erasing_regions:: NormalizationError ;
5
5
use crate :: ty:: { self , Ty , TyCtxt , TypeVisitableExt } ;
6
+ use hir:: Mutability ;
6
7
use rustc_error_messages:: DiagMessage ;
7
8
use rustc_errors:: {
8
9
Diag , DiagArgValue , DiagCtxt , Diagnostic , EmissionGuarantee , IntoDiagArg , Level ,
@@ -319,6 +320,8 @@ pub enum SizeSkeleton<'tcx> {
319
320
Pointer {
320
321
/// If true, this pointer is never null.
321
322
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 > ,
322
325
/// The type which determines the unsized metadata, if any,
323
326
/// of this pointer. Either a type parameter or a projection
324
327
/// depending on one, with regions erased.
@@ -372,7 +375,23 @@ impl<'tcx> SizeSkeleton<'tcx> {
372
375
match tail. kind ( ) {
373
376
ty:: Param ( _) | ty:: Alias ( ty:: Projection | ty:: Inherent , _) => {
374
377
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
+ } )
376
395
}
377
396
ty:: Error ( guar) => {
378
397
// Fixes ICE #124031
@@ -449,7 +468,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
449
468
let v0 = zero_or_ptr_variant ( 0 ) ?;
450
469
// Newtype.
451
470
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 {
453
472
return Ok ( SizeSkeleton :: Pointer {
454
473
non_zero : non_zero
455
474
|| match tcx. layout_scalar_valid_range ( def. did ( ) ) {
@@ -459,6 +478,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
459
478
}
460
479
_ => false ,
461
480
} ,
481
+ known_size,
462
482
tail,
463
483
} ) ;
464
484
} else {
@@ -469,9 +489,9 @@ impl<'tcx> SizeSkeleton<'tcx> {
469
489
let v1 = zero_or_ptr_variant ( 1 ) ?;
470
490
// Nullable pointer enum optimization.
471
491
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 } )
475
495
}
476
496
_ => Err ( err) ,
477
497
}
@@ -492,7 +512,10 @@ impl<'tcx> SizeSkeleton<'tcx> {
492
512
493
513
pub fn same_size ( self , other : SizeSkeleton < ' tcx > ) -> bool {
494
514
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,
496
519
( SizeSkeleton :: Pointer { tail : a, .. } , SizeSkeleton :: Pointer { tail : b, .. } ) => {
497
520
a == b
498
521
}
0 commit comments