@@ -205,10 +205,10 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
205
205
}
206
206
}
207
207
208
- fn layout_raw < ' tcx > (
208
+ fn layout_of < ' tcx > (
209
209
tcx : TyCtxt < ' tcx > ,
210
210
query : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
211
- ) -> Result < & ' tcx Layout , LayoutError < ' tcx > > {
211
+ ) -> Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > {
212
212
ty:: tls:: with_related_context ( tcx, move |icx| {
213
213
let ( param_env, ty) = query. into_parts ( ) ;
214
214
@@ -220,21 +220,33 @@ fn layout_raw<'tcx>(
220
220
let icx = ty:: tls:: ImplicitCtxt { layout_depth : icx. layout_depth + 1 , ..icx. clone ( ) } ;
221
221
222
222
ty:: tls:: enter_context ( & icx, |_| {
223
+ let param_env = param_env. with_reveal_all_normalized ( tcx) ;
224
+ let unnormalized_ty = ty;
225
+ let ty = tcx. normalize_erasing_regions ( param_env, ty) ;
226
+ if ty != unnormalized_ty {
227
+ // Ensure this layout is also cached for the normalized type.
228
+ return tcx. layout_of ( param_env. and ( ty) ) ;
229
+ }
230
+
223
231
let cx = LayoutCx { tcx, param_env } ;
224
- let layout = cx. layout_raw_uncached ( ty) ;
232
+
233
+ let layout = cx. layout_of_uncached ( ty) ?;
234
+ let layout = TyAndLayout { ty, layout } ;
235
+
236
+ cx. record_layout_for_printing ( layout) ;
237
+
225
238
// Type-level uninhabitedness should always imply ABI uninhabitedness.
226
- if let Ok ( layout) = layout {
227
- if tcx. conservative_is_privately_uninhabited ( param_env. and ( ty) ) {
228
- assert ! ( layout. abi. is_uninhabited( ) ) ;
229
- }
239
+ if tcx. conservative_is_privately_uninhabited ( param_env. and ( ty) ) {
240
+ assert ! ( layout. abi. is_uninhabited( ) ) ;
230
241
}
231
- layout
242
+
243
+ Ok ( layout)
232
244
} )
233
245
} )
234
246
}
235
247
236
248
pub fn provide ( providers : & mut ty:: query:: Providers ) {
237
- * providers = ty:: query:: Providers { layout_raw , ..* providers } ;
249
+ * providers = ty:: query:: Providers { layout_of , ..* providers } ;
238
250
}
239
251
240
252
pub struct LayoutCx < ' tcx , C > {
@@ -492,7 +504,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
492
504
} )
493
505
}
494
506
495
- fn layout_raw_uncached ( & self , ty : Ty < ' tcx > ) -> Result < & ' tcx Layout , LayoutError < ' tcx > > {
507
+ fn layout_of_uncached ( & self , ty : Ty < ' tcx > ) -> Result < & ' tcx Layout , LayoutError < ' tcx > > {
496
508
let tcx = self . tcx ;
497
509
let param_env = self . param_env ;
498
510
let dl = self . data_layout ( ) ;
@@ -889,7 +901,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
889
901
let present_first = match present_first {
890
902
Some ( present_first) => present_first,
891
903
// Uninhabited because it has no variants, or only absent ones.
892
- None if def. is_enum ( ) => return tcx. layout_raw ( param_env. and ( tcx. types . never ) ) ,
904
+ None if def. is_enum ( ) => {
905
+ return Ok ( tcx. layout_of ( param_env. and ( tcx. types . never ) ) ?. layout ) ;
906
+ }
893
907
// If it's a struct, still compute a layout so that we can still compute the
894
908
// field offsets.
895
909
None => VariantIdx :: new ( 0 ) ,
@@ -1368,11 +1382,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1368
1382
1369
1383
// Types with no meaningful known layout.
1370
1384
ty:: Projection ( _) | ty:: Opaque ( ..) => {
1371
- let normalized = tcx. normalize_erasing_regions ( param_env, ty) ;
1372
- if ty == normalized {
1373
- return Err ( LayoutError :: Unknown ( ty) ) ;
1374
- }
1375
- tcx. layout_raw ( param_env. and ( normalized) ) ?
1385
+ // NOTE(eddyb) `layout_of` query should've normalized these away,
1386
+ // if that was possible, so there's no reason to try again here.
1387
+ return Err ( LayoutError :: Unknown ( ty) ) ;
1376
1388
}
1377
1389
1378
1390
ty:: Placeholder ( ..) | ty:: GeneratorWitness ( ..) | ty:: Infer ( _) => {
@@ -1712,7 +1724,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1712
1724
Ok ( layout)
1713
1725
}
1714
1726
1715
- /// This is invoked by the `layout_raw ` query to record the final
1727
+ /// This is invoked by the `layout_of ` query to record the final
1716
1728
/// layout of each type.
1717
1729
#[ inline( always) ]
1718
1730
fn record_layout_for_printing ( & self , layout : TyAndLayout < ' tcx > ) {
@@ -2040,22 +2052,9 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
2040
2052
type TyAndLayout = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > ;
2041
2053
2042
2054
/// Computes the layout of a type. Note that this implicitly
2043
- /// executes in "reveal all" mode.
2055
+ /// executes in "reveal all" mode, and will normalize the input type .
2044
2056
fn layout_of ( & self , ty : Ty < ' tcx > ) -> Self :: TyAndLayout {
2045
- let param_env = self . param_env . with_reveal_all_normalized ( self . tcx ) ;
2046
- let ty = self . tcx . normalize_erasing_regions ( param_env, ty) ;
2047
- let layout = self . tcx . layout_raw ( param_env. and ( ty) ) ?;
2048
- let layout = TyAndLayout { ty, layout } ;
2049
-
2050
- // N.B., this recording is normally disabled; when enabled, it
2051
- // can however trigger recursive invocations of `layout_of`.
2052
- // Therefore, we execute it *after* the main query has
2053
- // completed, to avoid problems around recursive structures
2054
- // and the like. (Admittedly, I wasn't able to reproduce a problem
2055
- // here, but it seems like the right thing to do. -nmatsakis)
2056
- self . record_layout_for_printing ( layout) ;
2057
-
2058
- Ok ( layout)
2057
+ self . tcx . layout_of ( self . param_env . and ( ty) )
2059
2058
}
2060
2059
}
2061
2060
@@ -2064,50 +2063,9 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
2064
2063
type TyAndLayout = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > ;
2065
2064
2066
2065
/// Computes the layout of a type. Note that this implicitly
2067
- /// executes in "reveal all" mode.
2066
+ /// executes in "reveal all" mode, and will normalize the input type .
2068
2067
fn layout_of ( & self , ty : Ty < ' tcx > ) -> Self :: TyAndLayout {
2069
- let param_env = self . param_env . with_reveal_all_normalized ( * self . tcx ) ;
2070
- let ty = self . tcx . normalize_erasing_regions ( param_env, ty) ;
2071
- let layout = self . tcx . layout_raw ( param_env. and ( ty) ) ?;
2072
- let layout = TyAndLayout { ty, layout } ;
2073
-
2074
- // N.B., this recording is normally disabled; when enabled, it
2075
- // can however trigger recursive invocations of `layout_of`.
2076
- // Therefore, we execute it *after* the main query has
2077
- // completed, to avoid problems around recursive structures
2078
- // and the like. (Admittedly, I wasn't able to reproduce a problem
2079
- // here, but it seems like the right thing to do. -nmatsakis)
2080
- let cx = LayoutCx { tcx : * self . tcx , param_env : self . param_env } ;
2081
- cx. record_layout_for_printing ( layout) ;
2082
-
2083
- Ok ( layout)
2084
- }
2085
- }
2086
-
2087
- // Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users.
2088
- impl TyCtxt < ' tcx > {
2089
- /// Computes the layout of a type. Note that this implicitly
2090
- /// executes in "reveal all" mode.
2091
- #[ inline]
2092
- pub fn layout_of (
2093
- self ,
2094
- param_env_and_ty : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
2095
- ) -> Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > {
2096
- let cx = LayoutCx { tcx : self , param_env : param_env_and_ty. param_env } ;
2097
- cx. layout_of ( param_env_and_ty. value )
2098
- }
2099
- }
2100
-
2101
- impl ty:: query:: TyCtxtAt < ' tcx > {
2102
- /// Computes the layout of a type. Note that this implicitly
2103
- /// executes in "reveal all" mode.
2104
- #[ inline]
2105
- pub fn layout_of (
2106
- self ,
2107
- param_env_and_ty : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
2108
- ) -> Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > {
2109
- let cx = LayoutCx { tcx : self . at ( self . span ) , param_env : param_env_and_ty. param_env } ;
2110
- cx. layout_of ( param_env_and_ty. value )
2068
+ self . tcx . layout_of ( self . param_env . and ( ty) )
2111
2069
}
2112
2070
}
2113
2071
0 commit comments