@@ -197,23 +197,30 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
197197 return Ok ( * ty) ;
198198 }
199199
200+ let ( kind, data) = match * ty. kind ( ) {
201+ ty:: Alias ( kind, data) => ( kind, data) ,
202+ _ => {
203+ let res = ty. try_super_fold_with ( self ) ?;
204+ self . cache . insert ( ty, res) ;
205+ return Ok ( res) ;
206+ }
207+ } ;
208+
200209 // See note in `rustc_trait_selection::traits::project` about why we
201210 // wait to fold the substs.
202211
203212 // Wrap this in a closure so we don't accidentally return from the outer function
204- let res = match * ty . kind ( ) {
213+ let res = match kind {
205214 // This is really important. While we *can* handle this, this has
206215 // severe performance implications for large opaque types with
207216 // late-bound regions. See `issue-88862` benchmark.
208- ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } )
209- if !substs. has_escaping_bound_vars ( ) =>
210- {
217+ ty:: Opaque if !data. substs . has_escaping_bound_vars ( ) => {
211218 // Only normalize `impl Trait` outside of type inference, usually in codegen.
212219 match self . param_env . reveal ( ) {
213220 Reveal :: UserFacing => ty. try_super_fold_with ( self ) ?,
214221
215222 Reveal :: All => {
216- let substs = substs. try_fold_with ( self ) ?;
223+ let substs = data . substs . try_fold_with ( self ) ?;
217224 let recursion_limit = self . interner ( ) . recursion_limit ( ) ;
218225 if !recursion_limit. value_within_limit ( self . anon_depth ) {
219226 // A closure or generator may have itself as in its upvars.
@@ -228,7 +235,7 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
228235 return ty. try_super_fold_with ( self ) ;
229236 }
230237
231- let generic_ty = self . interner ( ) . type_of ( def_id) ;
238+ let generic_ty = self . interner ( ) . type_of ( data . def_id ) ;
232239 let concrete_ty = generic_ty. subst ( self . interner ( ) , substs) ;
233240 self . anon_depth += 1 ;
234241 if concrete_ty == ty {
@@ -248,62 +255,22 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
248255 }
249256 }
250257
251- ty:: Alias ( ty:: Projection , data) if !data. has_escaping_bound_vars ( ) => {
252- // This branch is just an optimization: when we don't have escaping bound vars,
253- // we don't need to replace them with placeholders (see branch below).
254-
255- let tcx = self . infcx . tcx ;
256- let data = data. try_fold_with ( self ) ?;
257-
258- let mut orig_values = OriginalQueryValues :: default ( ) ;
259- // HACK(matthewjasper) `'static` is special-cased in selection,
260- // so we cannot canonicalize it.
261- let c_data = self
262- . infcx
263- . canonicalize_query_keep_static ( self . param_env . and ( data) , & mut orig_values) ;
264- debug ! ( "QueryNormalizer: c_data = {:#?}" , c_data) ;
265- debug ! ( "QueryNormalizer: orig_values = {:#?}" , orig_values) ;
266- let result = tcx. normalize_projection_ty ( c_data) ?;
267- // We don't expect ambiguity.
268- if result. is_ambiguous ( ) {
269- // Rustdoc normalizes possibly not well-formed types, so only
270- // treat this as a bug if we're not in rustdoc.
271- if !tcx. sess . opts . actually_rustdoc {
272- tcx. sess . delay_span_bug (
273- DUMMY_SP ,
274- format ! ( "unexpected ambiguity: {:?} {:?}" , c_data, result) ,
275- ) ;
276- }
277- return Err ( NoSolution ) ;
278- }
279- let InferOk { value : result, obligations } =
280- self . infcx . instantiate_query_response_and_region_obligations (
281- self . cause ,
282- self . param_env ,
283- & orig_values,
284- result,
285- ) ?;
286- debug ! ( "QueryNormalizer: result = {:#?}" , result) ;
287- debug ! ( "QueryNormalizer: obligations = {:#?}" , obligations) ;
288- self . obligations . extend ( obligations) ;
289-
290- let res = result. normalized_ty ;
291- // `tcx.normalize_projection_ty` may normalize to a type that still has
292- // unevaluated consts, so keep normalizing here if that's the case.
293- if res != ty && res. has_type_flags ( ty:: TypeFlags :: HAS_CT_PROJECTION ) {
294- res. try_super_fold_with ( self ) ?
295- } else {
296- res
297- }
298- }
258+ ty:: Opaque => ty. try_super_fold_with ( self ) ?,
299259
300- ty:: Alias ( ty :: Projection , data ) => {
260+ ty:: Projection => {
301261 // See note in `rustc_trait_selection::traits::project`
302262
303263 let tcx = self . infcx . tcx ;
304264 let infcx = self . infcx ;
305- let ( data, mapped_regions, mapped_types, mapped_consts) =
306- BoundVarReplacer :: replace_bound_vars ( infcx, & mut self . universes , data) ;
265+ // Just an optimization: When we don't have escaping bound vars,
266+ // we don't need to replace them with placeholders.
267+ let ( data, maps) = if data. has_escaping_bound_vars ( ) {
268+ let ( data, mapped_regions, mapped_types, mapped_consts) =
269+ BoundVarReplacer :: replace_bound_vars ( infcx, & mut self . universes , data) ;
270+ ( data, Some ( ( mapped_regions, mapped_types, mapped_consts) ) )
271+ } else {
272+ ( data, None )
273+ } ;
307274 let data = data. try_fold_with ( self ) ?;
308275
309276 let mut orig_values = OriginalQueryValues :: default ( ) ;
@@ -337,14 +304,18 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
337304 debug ! ( "QueryNormalizer: result = {:#?}" , result) ;
338305 debug ! ( "QueryNormalizer: obligations = {:#?}" , obligations) ;
339306 self . obligations . extend ( obligations) ;
340- let res = PlaceholderReplacer :: replace_placeholders (
341- infcx,
342- mapped_regions,
343- mapped_types,
344- mapped_consts,
345- & self . universes ,
346- result. normalized_ty ,
347- ) ;
307+ let res = if let Some ( ( mapped_regions, mapped_types, mapped_consts) ) = maps {
308+ PlaceholderReplacer :: replace_placeholders (
309+ infcx,
310+ mapped_regions,
311+ mapped_types,
312+ mapped_consts,
313+ & self . universes ,
314+ result. normalized_ty ,
315+ )
316+ } else {
317+ result. normalized_ty
318+ } ;
348319 // `tcx.normalize_projection_ty` may normalize to a type that still has
349320 // unevaluated consts, so keep normalizing here if that's the case.
350321 if res != ty && res. has_type_flags ( ty:: TypeFlags :: HAS_CT_PROJECTION ) {
@@ -353,8 +324,6 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
353324 res
354325 }
355326 }
356-
357- _ => ty. try_super_fold_with ( self ) ?,
358327 } ;
359328
360329 self . cache . insert ( ty, res) ;
0 commit comments