@@ -15,7 +15,7 @@ use rustc_target::abi::call::FnAbi;
1515use rustc_target:: abi:: * ;
1616use rustc_target:: spec:: { abi:: Abi as SpecAbi , HasTargetSpec , PanicStrategy , Target } ;
1717
18- use std:: cmp:: { self , Ordering } ;
18+ use std:: cmp;
1919use std:: fmt;
2020use std:: num:: NonZeroUsize ;
2121use std:: ops:: Bound ;
@@ -316,8 +316,8 @@ impl<'tcx> SizeSkeleton<'tcx> {
316316 // First, try computing an exact naive layout (this covers simple types with generic
317317 // references, where a full static layout would fail).
318318 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 ) ) ;
321321 }
322322 }
323323
@@ -650,51 +650,146 @@ impl std::ops::DerefMut for TyAndNaiveLayout<'_> {
650650 }
651651}
652652
653- /// A naive underestimation of the layout of a type.
653+ /// Extremely simplified representation of a type's layout.
654+ ///
655+ ///
654656#[ derive( Copy , Clone , Debug , HashStable ) ]
655657pub 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+ }
660684}
661685
662686impl 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+ }
672694
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+ }
674718 }
675719
676720 #[ 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+ }
679727 self
680728 }
681729
682730 #[ 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
689738 }
690739
691740 #[ 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;
697747 }
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 }
698793 }
699794}
700795
0 commit comments