@@ -197,23 +197,30 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
197
197
return Ok ( * ty) ;
198
198
}
199
199
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
+
200
209
// See note in `rustc_trait_selection::traits::project` about why we
201
210
// wait to fold the substs.
202
211
203
212
// 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 {
205
214
// This is really important. While we *can* handle this, this has
206
215
// severe performance implications for large opaque types with
207
216
// 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 ( ) => {
211
218
// Only normalize `impl Trait` outside of type inference, usually in codegen.
212
219
match self . param_env . reveal ( ) {
213
220
Reveal :: UserFacing => ty. try_super_fold_with ( self ) ?,
214
221
215
222
Reveal :: All => {
216
- let substs = substs. try_fold_with ( self ) ?;
223
+ let substs = data . substs . try_fold_with ( self ) ?;
217
224
let recursion_limit = self . interner ( ) . recursion_limit ( ) ;
218
225
if !recursion_limit. value_within_limit ( self . anon_depth ) {
219
226
// 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>
228
235
return ty. try_super_fold_with ( self ) ;
229
236
}
230
237
231
- let generic_ty = self . interner ( ) . type_of ( def_id) ;
238
+ let generic_ty = self . interner ( ) . type_of ( data . def_id ) ;
232
239
let concrete_ty = generic_ty. subst ( self . interner ( ) , substs) ;
233
240
self . anon_depth += 1 ;
234
241
if concrete_ty == ty {
@@ -248,62 +255,22 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
248
255
}
249
256
}
250
257
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 ) ?,
299
259
300
- ty:: Alias ( ty :: Projection , data ) => {
260
+ ty:: Projection => {
301
261
// See note in `rustc_trait_selection::traits::project`
302
262
303
263
let tcx = self . infcx . tcx ;
304
264
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
+ } ;
307
274
let data = data. try_fold_with ( self ) ?;
308
275
309
276
let mut orig_values = OriginalQueryValues :: default ( ) ;
@@ -337,14 +304,18 @@ impl<'cx, 'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for QueryNormalizer<'cx, 'tcx>
337
304
debug ! ( "QueryNormalizer: result = {:#?}" , result) ;
338
305
debug ! ( "QueryNormalizer: obligations = {:#?}" , obligations) ;
339
306
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
+ } ;
348
319
// `tcx.normalize_projection_ty` may normalize to a type that still has
349
320
// unevaluated consts, so keep normalizing here if that's the case.
350
321
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>
353
324
res
354
325
}
355
326
}
356
-
357
- _ => ty. try_super_fold_with ( self ) ?,
358
327
} ;
359
328
360
329
self . cache . insert ( ty, res) ;
0 commit comments