@@ -15,7 +15,7 @@ use rustc_target::abi::call::FnAbi;
15
15
use rustc_target:: abi:: * ;
16
16
use rustc_target:: spec:: { abi:: Abi as SpecAbi , HasTargetSpec , PanicStrategy , Target } ;
17
17
18
- use std:: cmp:: { self , Ordering } ;
18
+ use std:: cmp;
19
19
use std:: fmt;
20
20
use std:: num:: NonZeroUsize ;
21
21
use std:: ops:: Bound ;
@@ -316,8 +316,8 @@ impl<'tcx> SizeSkeleton<'tcx> {
316
316
// First, try computing an exact naive layout (this covers simple types with generic
317
317
// references, where a full static layout would fail).
318
318
if let Ok ( layout) = tcx. naive_layout_of ( param_env. and ( ty) ) {
319
- if layout. is_exact {
320
- return Ok ( SizeSkeleton :: Known ( layout. min_size ) ) ;
319
+ if layout. exact {
320
+ return Ok ( SizeSkeleton :: Known ( layout. size ) ) ;
321
321
}
322
322
}
323
323
@@ -650,51 +650,146 @@ impl std::ops::DerefMut for TyAndNaiveLayout<'_> {
650
650
}
651
651
}
652
652
653
- /// A naive underestimation of the layout of a type.
653
+ /// Extremely simplified representation of a type's layout.
654
+ ///
655
+ ///
654
656
#[ derive( Copy , Clone , Debug , HashStable ) ]
655
657
pub struct NaiveLayout {
656
- pub min_size : Size ,
657
- pub min_align : Align ,
658
- // If `true`, `min_size` and `min_align` are guaranteed to be exact.
659
- pub is_exact : bool ,
658
+ pub abi : NaiveAbi ,
659
+ pub size : Size ,
660
+ pub align : Align ,
661
+ /// If `true`, `size` and `align` are exact.
662
+ pub exact : bool ,
663
+ }
664
+
665
+ #[ derive( Copy , Clone , Debug , Eq , PartialEq , HashStable ) ]
666
+ pub enum NaiveAbi {
667
+ /// A scalar layout, always implies `exact`.
668
+ Scalar ( Primitive ) ,
669
+ /// An uninhabited layout. (needed to properly track `Scalar`)
670
+ Uninhabited ,
671
+ /// An unsized aggregate. (needed to properly track `Scalar`)
672
+ Unsized ,
673
+ Any ,
674
+ }
675
+
676
+ impl NaiveAbi {
677
+ #[ inline]
678
+ pub fn as_aggregate ( self ) -> Self {
679
+ match self {
680
+ NaiveAbi :: Scalar ( _) => NaiveAbi :: Any ,
681
+ _ => self ,
682
+ }
683
+ }
660
684
}
661
685
662
686
impl NaiveLayout {
663
- pub const UNKNOWN : Self = Self { min_size : Size :: ZERO , min_align : Align :: ONE , is_exact : false } ;
664
- pub const EMPTY : Self = Self { min_size : Size :: ZERO , min_align : Align :: ONE , is_exact : true } ;
665
-
666
- pub fn is_compatible_with ( & self , layout : Layout < ' _ > ) -> bool {
667
- let cmp = |cmp : Ordering | match ( cmp, self . is_exact ) {
668
- ( Ordering :: Less | Ordering :: Equal , false ) => true ,
669
- ( Ordering :: Equal , true ) => true ,
670
- ( _, _) => false ,
671
- } ;
687
+ pub const EMPTY : Self =
688
+ Self { size : Size :: ZERO , align : Align :: ONE , exact : true , abi : NaiveAbi :: Any } ;
689
+
690
+ pub fn is_refined_by ( & self , layout : Layout < ' _ > ) -> bool {
691
+ if self . size > layout. size ( ) || self . align > layout. align ( ) . abi {
692
+ return false ;
693
+ }
672
694
673
- cmp ( self . min_size . cmp ( & layout. size ( ) ) ) && cmp ( self . min_align . cmp ( & layout. align ( ) . abi ) )
695
+ if let NaiveAbi :: Scalar ( prim) = self . abi {
696
+ assert ! ( self . exact) ;
697
+ if !matches ! ( layout. abi( ) , Abi :: Scalar ( s) if s. primitive( ) == prim) {
698
+ return false ;
699
+ }
700
+ }
701
+
702
+ !self . exact || ( self . size , self . align ) == ( layout. size ( ) , layout. align ( ) . abi )
703
+ }
704
+
705
+ /// Returns if this layout is known to be pointer-like (`None` if uncertain)
706
+ ///
707
+ /// See the corresponding `Layout::is_pointer_like` method.
708
+ pub fn is_pointer_like ( & self , dl : & TargetDataLayout ) -> Option < bool > {
709
+ match self . abi {
710
+ NaiveAbi :: Scalar ( _) => {
711
+ assert ! ( self . exact) ;
712
+ Some ( self . size == dl. pointer_size && self . align == dl. pointer_align . abi )
713
+ }
714
+ NaiveAbi :: Uninhabited | NaiveAbi :: Unsized => Some ( false ) ,
715
+ NaiveAbi :: Any if self . exact => Some ( false ) ,
716
+ NaiveAbi :: Any => None ,
717
+ }
674
718
}
675
719
676
720
#[ must_use]
677
- pub fn pad_to_align ( mut self ) -> Self {
678
- self . min_size = self . min_size . align_to ( self . min_align ) ;
721
+ #[ inline]
722
+ pub fn packed ( mut self , align : Align ) -> Self {
723
+ if self . align > align {
724
+ self . align = align;
725
+ self . abi = self . abi . as_aggregate ( ) ;
726
+ }
679
727
self
680
728
}
681
729
682
730
#[ must_use]
683
- pub fn concat < C : HasDataLayout > ( & self , other : & Self , cx : & C ) -> Option < Self > {
684
- Some ( Self {
685
- min_size : self . min_size . checked_add ( other. min_size , cx) ?,
686
- min_align : std:: cmp:: max ( self . min_align , other. min_align ) ,
687
- is_exact : self . is_exact && other. is_exact ,
688
- } )
731
+ #[ inline]
732
+ pub fn align_to ( mut self , align : Align ) -> Self {
733
+ if align > self . align {
734
+ self . align = align;
735
+ self . abi = self . abi . as_aggregate ( ) ;
736
+ }
737
+ self
689
738
}
690
739
691
740
#[ must_use]
692
- pub fn union ( & self , other : & Self ) -> Self {
693
- Self {
694
- min_size : std:: cmp:: max ( self . min_size , other. min_size ) ,
695
- min_align : std:: cmp:: max ( self . min_align , other. min_align ) ,
696
- is_exact : self . is_exact && other. is_exact ,
741
+ #[ inline]
742
+ pub fn pad_to_align ( mut self , align : Align ) -> Self {
743
+ let new_size = self . size . align_to ( align) ;
744
+ if new_size > self . size {
745
+ self . abi = self . abi . as_aggregate ( ) ;
746
+ self . size = new_size;
697
747
}
748
+ self
749
+ }
750
+
751
+ #[ must_use]
752
+ #[ inline]
753
+ pub fn concat ( & self , other : & Self , dl : & TargetDataLayout ) -> Option < Self > {
754
+ use NaiveAbi :: * ;
755
+
756
+ let size = self . size . checked_add ( other. size , dl) ?;
757
+ let align = cmp:: max ( self . align , other. align ) ;
758
+ let exact = self . exact && other. exact ;
759
+ let abi = match ( self . abi , other. abi ) {
760
+ // The uninhabited and unsized ABIs override everything.
761
+ ( Uninhabited , _) | ( _, Uninhabited ) => Uninhabited ,
762
+ ( Unsized , _) | ( _, Unsized ) => Unsized ,
763
+ // A scalar struct must have a single non ZST-field.
764
+ ( _, s @ Scalar ( _) ) if exact && self . size == Size :: ZERO => s,
765
+ ( s @ Scalar ( _) , _) if exact && other. size == Size :: ZERO => s,
766
+ // Default case.
767
+ ( _, _) => Any ,
768
+ } ;
769
+ Some ( Self { abi, size, align, exact } )
770
+ }
771
+
772
+ #[ must_use]
773
+ #[ inline]
774
+ pub fn union ( & self , other : & Self ) -> Self {
775
+ use NaiveAbi :: * ;
776
+
777
+ let size = cmp:: max ( self . size , other. size ) ;
778
+ let align = cmp:: max ( self . align , other. align ) ;
779
+ let exact = self . exact && other. exact ;
780
+ let abi = match ( self . abi , other. abi ) {
781
+ // The unsized ABI overrides everything.
782
+ ( Unsized , _) | ( _, Unsized ) => Unsized ,
783
+ // A scalar union must have a single non ZST-field.
784
+ ( _, s @ Scalar ( _) ) if exact && self . size == Size :: ZERO => s,
785
+ ( s @ Scalar ( _) , _) if exact && other. size == Size :: ZERO => s,
786
+ // ...or identical scalar fields.
787
+ ( Scalar ( s1) , Scalar ( s2) ) if s1 == s2 => Scalar ( s1) ,
788
+ // Default cases.
789
+ ( Uninhabited , Uninhabited ) => Uninhabited ,
790
+ ( _, _) => Any ,
791
+ } ;
792
+ Self { abi, size, align, exact }
698
793
}
699
794
}
700
795
0 commit comments