@@ -205,10 +205,10 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
205205 }
206206}
207207
208- fn layout_raw < ' tcx > (
208+ fn layout_of < ' tcx > (
209209 tcx : TyCtxt < ' tcx > ,
210210 query : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
211- ) -> Result < & ' tcx Layout , LayoutError < ' tcx > > {
211+ ) -> Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > {
212212 ty:: tls:: with_related_context ( tcx, move |icx| {
213213 let ( param_env, ty) = query. into_parts ( ) ;
214214
@@ -220,21 +220,33 @@ fn layout_raw<'tcx>(
220220 let icx = ty:: tls:: ImplicitCtxt { layout_depth : icx. layout_depth + 1 , ..icx. clone ( ) } ;
221221
222222 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+
223231 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+
225238 // 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( ) ) ;
230241 }
231- layout
242+
243+ Ok ( layout)
232244 } )
233245 } )
234246}
235247
236248pub fn provide ( providers : & mut ty:: query:: Providers ) {
237- * providers = ty:: query:: Providers { layout_raw , ..* providers } ;
249+ * providers = ty:: query:: Providers { layout_of , ..* providers } ;
238250}
239251
240252pub struct LayoutCx < ' tcx , C > {
@@ -492,7 +504,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
492504 } )
493505 }
494506
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 > > {
496508 let tcx = self . tcx ;
497509 let param_env = self . param_env ;
498510 let dl = self . data_layout ( ) ;
@@ -889,7 +901,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
889901 let present_first = match present_first {
890902 Some ( present_first) => present_first,
891903 // 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+ }
893907 // If it's a struct, still compute a layout so that we can still compute the
894908 // field offsets.
895909 None => VariantIdx :: new ( 0 ) ,
@@ -1368,11 +1382,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
13681382
13691383 // Types with no meaningful known layout.
13701384 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) ) ;
13761388 }
13771389
13781390 ty:: Placeholder ( ..) | ty:: GeneratorWitness ( ..) | ty:: Infer ( _) => {
@@ -1712,7 +1724,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
17121724 Ok ( layout)
17131725 }
17141726
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
17161728 /// layout of each type.
17171729 #[ inline( always) ]
17181730 fn record_layout_for_printing ( & self , layout : TyAndLayout < ' tcx > ) {
@@ -2040,22 +2052,9 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
20402052 type TyAndLayout = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > ;
20412053
20422054 /// 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 .
20442056 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) )
20592058 }
20602059}
20612060
@@ -2064,50 +2063,9 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
20642063 type TyAndLayout = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > ;
20652064
20662065 /// 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 .
20682067 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) )
21112069 }
21122070}
21132071
0 commit comments