@@ -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 ( ) ;
@@ -886,7 +898,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
886898 let present_first = match present_first {
887899 Some ( present_first) => present_first,
888900 // 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+ }
890904 // If it's a struct, still compute a layout so that we can still compute the
891905 // field offsets.
892906 None => VariantIdx :: new ( 0 ) ,
@@ -1362,11 +1376,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
13621376
13631377 // Types with no meaningful known layout.
13641378 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) ) ;
13701382 }
13711383
13721384 ty:: Placeholder ( ..) | ty:: GeneratorWitness ( ..) | ty:: Infer ( _) => {
@@ -1703,7 +1715,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
17031715 Ok ( layout)
17041716 }
17051717
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
17071719 /// layout of each type.
17081720 #[ inline( always) ]
17091721 fn record_layout_for_printing ( & self , layout : TyAndLayout < ' tcx > ) {
@@ -2031,22 +2043,9 @@ impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> {
20312043 type TyAndLayout = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > ;
20322044
20332045 /// 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 .
20352047 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) )
20502049 }
20512050}
20522051
@@ -2055,50 +2054,9 @@ impl LayoutOf for LayoutCx<'tcx, ty::query::TyCtxtAt<'tcx>> {
20552054 type TyAndLayout = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > ;
20562055
20572056 /// 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 .
20592058 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) )
21022060 }
21032061}
21042062
0 commit comments