1
1
//! Compute the binary representation of a type
2
2
3
- use std:: { borrow :: Cow , fmt} ;
3
+ use std:: fmt;
4
4
5
5
use base_db:: salsa:: Cycle ;
6
6
use chalk_ir:: { AdtId , FloatTy , IntTy , TyKind , UintTy } ;
7
7
use hir_def:: {
8
8
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 ,
11
11
} ,
12
12
LocalFieldId , StructId ,
13
13
} ;
14
14
use la_arena:: { Idx , RawIdx } ;
15
15
use rustc_abi:: AddressSpace ;
16
16
use rustc_index:: { IndexSlice , IndexVec } ;
17
17
18
- use stdx:: never;
19
18
use triomphe:: Arc ;
20
19
21
20
use crate :: {
@@ -73,6 +72,7 @@ pub type Variants = hir_def::layout::Variants<RustcFieldIdx, RustcEnumVariantIdx
73
72
74
73
#[ derive( Debug , PartialEq , Eq , Clone ) ]
75
74
pub enum LayoutError {
75
+ EmptyUnion ,
76
76
HasErrorConst ,
77
77
HasErrorType ,
78
78
HasPlaceholder ,
@@ -81,6 +81,7 @@ pub enum LayoutError {
81
81
RecursiveTypeWithoutIndirection ,
82
82
SizeOverflow ,
83
83
TargetLayoutNotAvailable ,
84
+ UnexpectedUnsized ,
84
85
Unknown ,
85
86
UserReprTooSmall ,
86
87
}
@@ -89,6 +90,7 @@ impl std::error::Error for LayoutError {}
89
90
impl fmt:: Display for LayoutError {
90
91
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
91
92
match self {
93
+ LayoutError :: EmptyUnion => write ! ( f, "type is an union with no fields" ) ,
92
94
LayoutError :: HasErrorConst => write ! ( f, "type contains an unevaluatable const" ) ,
93
95
LayoutError :: HasErrorType => write ! ( f, "type contains an error" ) ,
94
96
LayoutError :: HasPlaceholder => write ! ( f, "type contains placeholders" ) ,
@@ -99,6 +101,9 @@ impl fmt::Display for LayoutError {
99
101
}
100
102
LayoutError :: SizeOverflow => write ! ( f, "size overflow" ) ,
101
103
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
+ }
102
107
LayoutError :: Unknown => write ! ( f, "unknown" ) ,
103
108
LayoutError :: UserReprTooSmall => {
104
109
write ! ( f, "the `#[repr]` hint is too small to hold the discriminants of the enum" )
@@ -107,19 +112,23 @@ impl fmt::Display for LayoutError {
107
112
}
108
113
}
109
114
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
+ }
112
123
}
113
124
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
+ }
120
128
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) }
123
132
}
124
133
}
125
134
@@ -205,8 +214,8 @@ pub fn layout_of_ty_query(
205
214
let Ok ( target) = db. target_data_layout ( krate) else {
206
215
return Err ( LayoutError :: TargetLayoutNotAvailable ) ;
207
216
} ;
208
- let cx = LayoutCx { target : & target } ;
209
- let dl = cx . current_data_layout ( ) ;
217
+ let dl = & * target;
218
+ let cx = LayoutCx :: new ( dl ) ;
210
219
let ty = normalize ( db, trait_env. clone ( ) , ty) ;
211
220
let result = match ty. kind ( Interner ) {
212
221
TyKind :: Adt ( AdtId ( def) , subst) => {
@@ -281,7 +290,7 @@ pub fn layout_of_ty_query(
281
290
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
282
291
let fields = fields. iter ( ) . map ( |it| & * * it) . collect :: < Vec < _ > > ( ) ;
283
292
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) ?
285
294
}
286
295
TyKind :: Array ( element, count) => {
287
296
let count = try_const_usize ( db, count) . ok_or ( LayoutError :: HasErrorConst ) ? as u64 ;
@@ -367,12 +376,12 @@ pub fn layout_of_ty_query(
367
376
} ;
368
377
369
378
// Effectively a (ptr, meta) tuple.
370
- cx. scalar_pair ( data_ptr, metadata)
379
+ cx. calc . scalar_pair ( data_ptr, metadata)
371
380
}
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 ( ) ,
374
383
TyKind :: Dyn ( _) | TyKind :: Foreign ( _) => {
375
- let mut unit = layout_of_unit ( & cx, dl ) ?;
384
+ let mut unit = layout_of_unit ( & cx) ?;
376
385
match & mut unit. abi {
377
386
Abi :: Aggregate { sized } => * sized = false ,
378
387
_ => return Err ( LayoutError :: Unknown ) ,
@@ -414,8 +423,7 @@ pub fn layout_of_ty_query(
414
423
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
415
424
let fields = fields. iter ( ) . map ( |it| & * * it) . collect :: < Vec < _ > > ( ) ;
416
425
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 ) ?
419
427
}
420
428
TyKind :: Coroutine ( _, _) | TyKind :: CoroutineWitness ( _, _) => {
421
429
return Err ( LayoutError :: NotImplemented )
@@ -447,14 +455,14 @@ pub fn layout_of_ty_recover(
447
455
Err ( LayoutError :: RecursiveTypeWithoutIndirection )
448
456
}
449
457
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 )
458
466
}
459
467
460
468
fn struct_tail_erasing_lifetimes ( db : & dyn HirDatabase , pointee : Ty ) -> Ty {
0 commit comments