@@ -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 ( ) ;
@@ -886,7 +898,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
886
898
let present_first = match present_first {
887
899
Some ( present_first) => present_first,
888
900
// Uninhabited because it has no variants, or only absent ones.
889
- None if def. is_enum ( ) => return tcx. layout_raw ( param_env. and ( tcx. types . never ) ) ,
901
+ None if def. is_enum ( ) => {
902
+ return Ok ( tcx. layout_of ( param_env. and ( tcx. types . never ) ) ?. layout ) ;
903
+ }
890
904
// If it's a struct, still compute a layout so that we can still compute the
891
905
// field offsets.
892
906
None => VariantIdx :: new ( 0 ) ,
@@ -1362,11 +1376,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1362
1376
1363
1377
// Types with no meaningful known layout.
1364
1378
ty:: Projection ( _) | ty:: Opaque ( ..) => {
1365
- let normalized = tcx. normalize_erasing_regions ( param_env, ty) ;
1366
- if ty == normalized {
1367
- return Err ( LayoutError :: Unknown ( ty) ) ;
1368
- }
1369
- tcx. layout_raw ( param_env. and ( normalized) ) ?
1379
+ // NOTE(eddyb) `layout_of` query should've normalized these away,
1380
+ // if that was possible, so there's no reason to try again here.
1381
+ return Err ( LayoutError :: Unknown ( ty) ) ;
1370
1382
}
1371
1383
1372
1384
ty:: Placeholder ( ..) | ty:: GeneratorWitness ( ..) | ty:: Infer ( _) => {
@@ -1703,7 +1715,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
1703
1715
Ok ( layout)
1704
1716
}
1705
1717
1706
- /// This is invoked by the `layout_raw ` query to record the final
1718
+ /// This is invoked by the `layout_of ` query to record the final
1707
1719
/// layout of each type.
1708
1720
#[ inline( always) ]
1709
1721
fn record_layout_for_printing ( & self , layout : TyAndLayout < ' tcx > ) {
@@ -2031,22 +2043,9 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
2031
2043
type TyAndLayout = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > ;
2032
2044
2033
2045
/// Computes the layout of a type. Note that this implicitly
2034
- /// executes in "reveal all" mode.
2046
+ /// executes in "reveal all" mode, and will normalize the input type .
2035
2047
fn layout_of ( & self , ty : Ty < ' tcx > ) -> Self :: TyAndLayout {
2036
- let param_env = self . param_env . with_reveal_all_normalized ( self . tcx ) ;
2037
- let ty = self . tcx . normalize_erasing_regions ( param_env, ty) ;
2038
- let layout = self . tcx . layout_raw ( param_env. and ( ty) ) ?;
2039
- let layout = TyAndLayout { ty, layout } ;
2040
-
2041
- // N.B., this recording is normally disabled; when enabled, it
2042
- // can however trigger recursive invocations of `layout_of`.
2043
- // Therefore, we execute it *after* the main query has
2044
- // completed, to avoid problems around recursive structures
2045
- // and the like. (Admittedly, I wasn't able to reproduce a problem
2046
- // here, but it seems like the right thing to do. -nmatsakis)
2047
- self . record_layout_for_printing ( layout) ;
2048
-
2049
- Ok ( layout)
2048
+ self . tcx . layout_of ( self . param_env . and ( ty) )
2050
2049
}
2051
2050
}
2052
2051
@@ -2055,50 +2054,9 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
2055
2054
type TyAndLayout = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > ;
2056
2055
2057
2056
/// Computes the layout of a type. Note that this implicitly
2058
- /// executes in "reveal all" mode.
2057
+ /// executes in "reveal all" mode, and will normalize the input type .
2059
2058
fn layout_of ( & self , ty : Ty < ' tcx > ) -> Self :: TyAndLayout {
2060
- let param_env = self . param_env . with_reveal_all_normalized ( * self . tcx ) ;
2061
- let ty = self . tcx . normalize_erasing_regions ( param_env, ty) ;
2062
- let layout = self . tcx . layout_raw ( param_env. and ( ty) ) ?;
2063
- let layout = TyAndLayout { ty, layout } ;
2064
-
2065
- // N.B., this recording is normally disabled; when enabled, it
2066
- // can however trigger recursive invocations of `layout_of`.
2067
- // Therefore, we execute it *after* the main query has
2068
- // completed, to avoid problems around recursive structures
2069
- // and the like. (Admittedly, I wasn't able to reproduce a problem
2070
- // here, but it seems like the right thing to do. -nmatsakis)
2071
- let cx = LayoutCx { tcx : * self . tcx , param_env : self . param_env } ;
2072
- cx. record_layout_for_printing ( layout) ;
2073
-
2074
- Ok ( layout)
2075
- }
2076
- }
2077
-
2078
- // Helper (inherent) `layout_of` methods to avoid pushing `LayoutCx` to users.
2079
- impl TyCtxt < ' tcx > {
2080
- /// Computes the layout of a type. Note that this implicitly
2081
- /// executes in "reveal all" mode.
2082
- #[ inline]
2083
- pub fn layout_of (
2084
- self ,
2085
- param_env_and_ty : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
2086
- ) -> Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > {
2087
- let cx = LayoutCx { tcx : self , param_env : param_env_and_ty. param_env } ;
2088
- cx. layout_of ( param_env_and_ty. value )
2089
- }
2090
- }
2091
-
2092
- impl ty:: query:: TyCtxtAt < ' tcx > {
2093
- /// Computes the layout of a type. Note that this implicitly
2094
- /// executes in "reveal all" mode.
2095
- #[ inline]
2096
- pub fn layout_of (
2097
- self ,
2098
- param_env_and_ty : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
2099
- ) -> Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > {
2100
- let cx = LayoutCx { tcx : self . at ( self . span ) , param_env : param_env_and_ty. param_env } ;
2101
- cx. layout_of ( param_env_and_ty. value )
2059
+ self . tcx . layout_of ( self . param_env . and ( ty) )
2102
2060
}
2103
2061
}
2104
2062
0 commit comments