11//! Compute the binary representation of a type
22
3- use std:: { borrow :: Cow , fmt} ;
3+ use std:: fmt;
44
55use base_db:: salsa:: Cycle ;
66use chalk_ir:: { AdtId , FloatTy , IntTy , TyKind , UintTy } ;
77use hir_def:: {
88 layout:: {
9- Abi , FieldsShape , Float , Integer , LayoutCalculator , LayoutS , Primitive , ReprOptions ,
10- Scalar , Size , StructKind , TargetDataLayout , WrappingRange ,
9+ Abi , FieldsShape , Float , Integer , LayoutCalculator , LayoutCalculatorError , LayoutS ,
10+ Primitive , ReprOptions , Scalar , Size , StructKind , TargetDataLayout , WrappingRange ,
1111 } ,
1212 LocalFieldId , StructId ,
1313} ;
1414use la_arena:: { Idx , RawIdx } ;
1515use rustc_abi:: AddressSpace ;
1616use rustc_index:: { IndexSlice , IndexVec } ;
1717
18- use stdx:: never;
1918use triomphe:: Arc ;
2019
2120use crate :: {
@@ -73,6 +72,7 @@ pub type Variants = hir_def::layout::Variants<RustcFieldIdx, RustcEnumVariantIdx
7372
7473#[ derive( Debug , PartialEq , Eq , Clone ) ]
7574pub enum LayoutError {
75+ EmptyUnion ,
7676 HasErrorConst ,
7777 HasErrorType ,
7878 HasPlaceholder ,
@@ -81,6 +81,7 @@ pub enum LayoutError {
8181 RecursiveTypeWithoutIndirection ,
8282 SizeOverflow ,
8383 TargetLayoutNotAvailable ,
84+ UnexpectedUnsized ,
8485 Unknown ,
8586 UserReprTooSmall ,
8687}
@@ -89,6 +90,7 @@ impl std::error::Error for LayoutError {}
8990impl fmt:: Display for LayoutError {
9091 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
9192 match self {
93+ LayoutError :: EmptyUnion => write ! ( f, "type is an union with no fields" ) ,
9294 LayoutError :: HasErrorConst => write ! ( f, "type contains an unevaluatable const" ) ,
9395 LayoutError :: HasErrorType => write ! ( f, "type contains an error" ) ,
9496 LayoutError :: HasPlaceholder => write ! ( f, "type contains placeholders" ) ,
@@ -99,6 +101,9 @@ impl fmt::Display for LayoutError {
99101 }
100102 LayoutError :: SizeOverflow => write ! ( f, "size overflow" ) ,
101103 LayoutError :: TargetLayoutNotAvailable => write ! ( f, "target layout not available" ) ,
104+ LayoutError :: UnexpectedUnsized => {
105+ write ! ( f, "an unsized type was found where a sized type was expected" )
106+ }
102107 LayoutError :: Unknown => write ! ( f, "unknown" ) ,
103108 LayoutError :: UserReprTooSmall => {
104109 write ! ( f, "the `#[repr]` hint is too small to hold the discriminants of the enum" )
@@ -107,19 +112,23 @@ impl fmt::Display for LayoutError {
107112 }
108113}
109114
110- struct LayoutCx < ' a > {
111- target : & ' a TargetDataLayout ,
115+ impl < F > From < LayoutCalculatorError < F > > for LayoutError {
116+ fn from ( err : LayoutCalculatorError < F > ) -> Self {
117+ match err {
118+ LayoutCalculatorError :: EmptyUnion => LayoutError :: EmptyUnion ,
119+ LayoutCalculatorError :: UnexpectedUnsized ( _) => LayoutError :: UnexpectedUnsized ,
120+ LayoutCalculatorError :: SizeOverflow => LayoutError :: SizeOverflow ,
121+ }
122+ }
112123}
113124
114- impl < ' a > LayoutCalculator for LayoutCx < ' a > {
115- type TargetDataLayoutRef = & ' a TargetDataLayout ;
116-
117- fn delayed_bug ( & self , txt : impl Into < Cow < ' static , str > > ) {
118- never ! ( "{}" , txt. into( ) ) ;
119- }
125+ struct LayoutCx < ' a > {
126+ calc : LayoutCalculator < & ' a TargetDataLayout > ,
127+ }
120128
121- fn current_data_layout ( & self ) -> & ' a TargetDataLayout {
122- self . target
129+ impl < ' a > LayoutCx < ' a > {
130+ fn new ( target : & ' a TargetDataLayout ) -> Self {
131+ Self { calc : LayoutCalculator :: new ( target) }
123132 }
124133}
125134
@@ -205,8 +214,8 @@ pub fn layout_of_ty_query(
205214 let Ok ( target) = db. target_data_layout ( krate) else {
206215 return Err ( LayoutError :: TargetLayoutNotAvailable ) ;
207216 } ;
208- let cx = LayoutCx { target : & target } ;
209- let dl = cx . current_data_layout ( ) ;
217+ let dl = & * target;
218+ let cx = LayoutCx :: new ( dl ) ;
210219 let ty = normalize ( db, trait_env. clone ( ) , ty) ;
211220 let result = match ty. kind ( Interner ) {
212221 TyKind :: Adt ( AdtId ( def) , subst) => {
@@ -281,7 +290,7 @@ pub fn layout_of_ty_query(
281290 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
282291 let fields = fields. iter ( ) . map ( |it| & * * it) . collect :: < Vec < _ > > ( ) ;
283292 let fields = fields. iter ( ) . collect :: < IndexVec < _ , _ > > ( ) ;
284- cx. univariant ( dl , & fields, & ReprOptions :: default ( ) , kind) . ok_or ( LayoutError :: Unknown ) ?
293+ cx. calc . univariant ( & fields, & ReprOptions :: default ( ) , kind) ?
285294 }
286295 TyKind :: Array ( element, count) => {
287296 let count = try_const_usize ( db, count) . ok_or ( LayoutError :: HasErrorConst ) ? as u64 ;
@@ -367,12 +376,12 @@ pub fn layout_of_ty_query(
367376 } ;
368377
369378 // Effectively a (ptr, meta) tuple.
370- cx. scalar_pair ( data_ptr, metadata)
379+ cx. calc . scalar_pair ( data_ptr, metadata)
371380 }
372- TyKind :: FnDef ( _, _) => layout_of_unit ( & cx, dl ) ?,
373- TyKind :: Never => cx. layout_of_never_type ( ) ,
381+ TyKind :: FnDef ( _, _) => layout_of_unit ( & cx) ?,
382+ TyKind :: Never => cx. calc . layout_of_never_type ( ) ,
374383 TyKind :: Dyn ( _) | TyKind :: Foreign ( _) => {
375- let mut unit = layout_of_unit ( & cx, dl ) ?;
384+ let mut unit = layout_of_unit ( & cx) ?;
376385 match & mut unit. abi {
377386 Abi :: Aggregate { sized } => * sized = false ,
378387 _ => return Err ( LayoutError :: Unknown ) ,
@@ -414,8 +423,7 @@ pub fn layout_of_ty_query(
414423 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
415424 let fields = fields. iter ( ) . map ( |it| & * * it) . collect :: < Vec < _ > > ( ) ;
416425 let fields = fields. iter ( ) . collect :: < IndexVec < _ , _ > > ( ) ;
417- cx. univariant ( dl, & fields, & ReprOptions :: default ( ) , StructKind :: AlwaysSized )
418- . ok_or ( LayoutError :: Unknown ) ?
426+ cx. calc . univariant ( & fields, & ReprOptions :: default ( ) , StructKind :: AlwaysSized ) ?
419427 }
420428 TyKind :: Coroutine ( _, _) | TyKind :: CoroutineWitness ( _, _) => {
421429 return Err ( LayoutError :: NotImplemented )
@@ -447,14 +455,14 @@ pub fn layout_of_ty_recover(
447455 Err ( LayoutError :: RecursiveTypeWithoutIndirection )
448456}
449457
450- fn layout_of_unit ( cx : & LayoutCx < ' _ > , dl : & TargetDataLayout ) -> Result < Layout , LayoutError > {
451- cx. univariant :: < RustcFieldIdx , RustcEnumVariantIdx , & & Layout > (
452- dl ,
453- IndexSlice :: empty ( ) ,
454- & ReprOptions :: default ( ) ,
455- StructKind :: AlwaysSized ,
456- )
457- . ok_or ( LayoutError :: Unknown )
458+ fn layout_of_unit ( cx : & LayoutCx < ' _ > ) -> Result < Layout , LayoutError > {
459+ cx. calc
460+ . univariant :: < RustcFieldIdx , RustcEnumVariantIdx , & & Layout > (
461+ IndexSlice :: empty ( ) ,
462+ & ReprOptions :: default ( ) ,
463+ StructKind :: AlwaysSized ,
464+ )
465+ . map_err ( Into :: into )
458466}
459467
460468fn struct_tail_erasing_lifetimes ( db : & dyn HirDatabase , pointee : Ty ) -> Ty {
0 commit comments