@@ -10,8 +10,8 @@ use rustc_macros::extension;
10
10
use rustc_middle:: span_bug;
11
11
use rustc_middle:: traits:: { ObligationCause , ObligationCauseCode } ;
12
12
use rustc_middle:: ty:: {
13
- self , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitable , TypeVisitableExt ,
14
- TypingMode ,
13
+ self , AliasTy , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeVisitable ,
14
+ TypeVisitableExt , TypingMode ,
15
15
} ;
16
16
use tracing:: { debug, instrument} ;
17
17
@@ -178,6 +178,163 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
178
178
179
179
if !needs_normalization ( self . selcx . infcx , & value) { value } else { value. fold_with ( self ) }
180
180
}
181
+
182
+ fn normalize_trait_projection ( & mut self , data : AliasTy < ' tcx > ) -> Ty < ' tcx > {
183
+ if !data. has_escaping_bound_vars ( ) {
184
+ // When we don't have escaping bound vars we can normalize ambig aliases
185
+ // to inference variables (done in `normalize_projection_ty`). This would
186
+ // be wrong if there were escaping bound vars as even if we instantiated
187
+ // the bound vars with placeholders, we wouldn't be able to map them back
188
+ // after normalization succeeded.
189
+ //
190
+ // Also, as an optimization: when we don't have escaping bound vars, we don't
191
+ // need to replace them with placeholders (see branch below).
192
+ let data = data. fold_with ( self ) ;
193
+ let normalized_ty = project:: normalize_projection_ty (
194
+ self . selcx ,
195
+ self . param_env ,
196
+ data,
197
+ self . cause . clone ( ) ,
198
+ self . depth ,
199
+ self . obligations ,
200
+ ) ;
201
+ debug ! (
202
+ ?self . depth,
203
+ ?ty,
204
+ ?normalized_ty,
205
+ obligations. len = ?self . obligations. len( ) ,
206
+ "AssocTypeNormalizer: normalized type"
207
+ ) ;
208
+ normalized_ty. expect_type ( )
209
+ } else {
210
+ // If there are escaping bound vars, we temporarily replace the
211
+ // bound vars with placeholders. Note though, that in the case
212
+ // that we still can't project for whatever reason (e.g. self
213
+ // type isn't known enough), we *can't* register an obligation
214
+ // and return an inference variable (since then that obligation
215
+ // would have bound vars and that's a can of worms). Instead,
216
+ // we just give up and fall back to pretending like we never tried!
217
+ //
218
+ // Note: this isn't necessarily the final approach here; we may
219
+ // want to figure out how to register obligations with escaping vars
220
+ // or handle this some other way.
221
+
222
+ let infcx = self . selcx . infcx ;
223
+ let ( data, mapped_regions, mapped_types, mapped_consts) =
224
+ BoundVarReplacer :: replace_bound_vars ( infcx, & mut self . universes , data) ;
225
+ let data = data. fold_with ( self ) ;
226
+ let normalized_ty = project:: opt_normalize_projection_term (
227
+ self . selcx ,
228
+ self . param_env ,
229
+ data. into ( ) ,
230
+ self . cause . clone ( ) ,
231
+ self . depth ,
232
+ self . obligations ,
233
+ )
234
+ . ok ( )
235
+ . flatten ( )
236
+ . map ( |term| term. expect_type ( ) )
237
+ . map ( |normalized_ty| {
238
+ PlaceholderReplacer :: replace_placeholders (
239
+ infcx,
240
+ mapped_regions,
241
+ mapped_types,
242
+ mapped_consts,
243
+ & self . universes ,
244
+ normalized_ty,
245
+ )
246
+ } )
247
+ . unwrap_or_else ( || ty. super_fold_with ( self ) ) ;
248
+
249
+ debug ! (
250
+ ?self . depth,
251
+ ?ty,
252
+ ?normalized_ty,
253
+ obligations. len = ?self . obligations. len( ) ,
254
+ "AssocTypeNormalizer: normalized type"
255
+ ) ;
256
+ normalized_ty
257
+ }
258
+ }
259
+
260
+ fn normalize_inherent_projection ( & mut self , data : AliasTy < ' tcx > ) -> Ty < ' tcx > {
261
+ if !data. has_escaping_bound_vars ( ) {
262
+ // This branch is *mostly* just an optimization: when we don't
263
+ // have escaping bound vars, we don't need to replace them with
264
+ // placeholders (see branch below). *Also*, we know that we can
265
+ // register an obligation to *later* project, since we know
266
+ // there won't be bound vars there.
267
+
268
+ let data = data. fold_with ( self ) ;
269
+
270
+ project:: normalize_inherent_projection (
271
+ self . selcx ,
272
+ self . param_env ,
273
+ data,
274
+ self . cause . clone ( ) ,
275
+ self . depth ,
276
+ self . obligations ,
277
+ )
278
+ } else {
279
+ let infcx = self . selcx . infcx ;
280
+ let ( data, mapped_regions, mapped_types, mapped_consts) =
281
+ BoundVarReplacer :: replace_bound_vars ( infcx, & mut self . universes , data) ;
282
+ let data = data. fold_with ( self ) ;
283
+ let ty = project:: normalize_inherent_projection (
284
+ self . selcx ,
285
+ self . param_env ,
286
+ data,
287
+ self . cause . clone ( ) ,
288
+ self . depth ,
289
+ self . obligations ,
290
+ ) ;
291
+
292
+ PlaceholderReplacer :: replace_placeholders (
293
+ infcx,
294
+ mapped_regions,
295
+ mapped_types,
296
+ mapped_consts,
297
+ & self . universes ,
298
+ ty,
299
+ )
300
+ }
301
+ }
302
+
303
+ fn normalize_free_alias ( & mut self , data : AliasTy < ' tcx > ) -> Ty < ' tcx > {
304
+ let recursion_limit = self . cx ( ) . recursion_limit ( ) ;
305
+ if !recursion_limit. value_within_limit ( self . depth ) {
306
+ self . selcx . infcx . err_ctxt ( ) . report_overflow_error (
307
+ OverflowCause :: DeeplyNormalize ( data. into ( ) ) ,
308
+ self . cause . span ,
309
+ false ,
310
+ |diag| {
311
+ diag. note ( crate :: fluent_generated:: trait_selection_ty_alias_overflow) ;
312
+ } ,
313
+ ) ;
314
+ }
315
+
316
+ let infcx = self . selcx . infcx ;
317
+ self . obligations . extend (
318
+ infcx. tcx . predicates_of ( data. def_id ) . instantiate_own ( infcx. tcx , data. args ) . map (
319
+ |( mut predicate, span) | {
320
+ if data. has_escaping_bound_vars ( ) {
321
+ ( predicate, ..) = BoundVarReplacer :: replace_bound_vars (
322
+ infcx,
323
+ & mut self . universes ,
324
+ predicate,
325
+ ) ;
326
+ }
327
+ let mut cause = self . cause . clone ( ) ;
328
+ cause. map_code ( |code| ObligationCauseCode :: TypeAlias ( code, span, data. def_id ) ) ;
329
+ Obligation :: new ( infcx. tcx , cause, self . param_env , predicate)
330
+ } ,
331
+ ) ,
332
+ ) ;
333
+ self . depth += 1 ;
334
+ let res = infcx. tcx . type_of ( data. def_id ) . instantiate ( infcx. tcx , data. args ) . fold_with ( self ) ;
335
+ self . depth -= 1 ;
336
+ res
337
+ }
181
338
}
182
339
183
340
impl < ' a , ' b , ' tcx > TypeFolder < TyCtxt < ' tcx > > for AssocTypeNormalizer < ' a , ' b , ' tcx > {
@@ -258,168 +415,9 @@ impl<'a, 'b, 'tcx> TypeFolder<TyCtxt<'tcx>> for AssocTypeNormalizer<'a, 'b, 'tcx
258
415
}
259
416
}
260
417
}
261
-
262
- ty:: Projection if !data. has_escaping_bound_vars ( ) => {
263
- // When we don't have escaping bound vars we can normalize ambig aliases
264
- // to inference variables (done in `normalize_projection_ty`). This would
265
- // be wrong if there were escaping bound vars as even if we instantiated
266
- // the bound vars with placeholders, we wouldn't be able to map them back
267
- // after normalization succeeded.
268
- //
269
- // Also, as an optimization: when we don't have escaping bound vars, we don't
270
- // need to replace them with placeholders (see branch below).
271
- let data = data. fold_with ( self ) ;
272
- let normalized_ty = project:: normalize_projection_ty (
273
- self . selcx ,
274
- self . param_env ,
275
- data,
276
- self . cause . clone ( ) ,
277
- self . depth ,
278
- self . obligations ,
279
- ) ;
280
- debug ! (
281
- ?self . depth,
282
- ?ty,
283
- ?normalized_ty,
284
- obligations. len = ?self . obligations. len( ) ,
285
- "AssocTypeNormalizer: normalized type"
286
- ) ;
287
- normalized_ty. expect_type ( )
288
- }
289
-
290
- ty:: Projection => {
291
- // If there are escaping bound vars, we temporarily replace the
292
- // bound vars with placeholders. Note though, that in the case
293
- // that we still can't project for whatever reason (e.g. self
294
- // type isn't known enough), we *can't* register an obligation
295
- // and return an inference variable (since then that obligation
296
- // would have bound vars and that's a can of worms). Instead,
297
- // we just give up and fall back to pretending like we never tried!
298
- //
299
- // Note: this isn't necessarily the final approach here; we may
300
- // want to figure out how to register obligations with escaping vars
301
- // or handle this some other way.
302
-
303
- let infcx = self . selcx . infcx ;
304
- let ( data, mapped_regions, mapped_types, mapped_consts) =
305
- BoundVarReplacer :: replace_bound_vars ( infcx, & mut self . universes , data) ;
306
- let data = data. fold_with ( self ) ;
307
- let normalized_ty = project:: opt_normalize_projection_term (
308
- self . selcx ,
309
- self . param_env ,
310
- data. into ( ) ,
311
- self . cause . clone ( ) ,
312
- self . depth ,
313
- self . obligations ,
314
- )
315
- . ok ( )
316
- . flatten ( )
317
- . map ( |term| term. expect_type ( ) )
318
- . map ( |normalized_ty| {
319
- PlaceholderReplacer :: replace_placeholders (
320
- infcx,
321
- mapped_regions,
322
- mapped_types,
323
- mapped_consts,
324
- & self . universes ,
325
- normalized_ty,
326
- )
327
- } )
328
- . unwrap_or_else ( || ty. super_fold_with ( self ) ) ;
329
-
330
- debug ! (
331
- ?self . depth,
332
- ?ty,
333
- ?normalized_ty,
334
- obligations. len = ?self . obligations. len( ) ,
335
- "AssocTypeNormalizer: normalized type"
336
- ) ;
337
- normalized_ty
338
- }
339
- ty:: Free => {
340
- let recursion_limit = self . cx ( ) . recursion_limit ( ) ;
341
- if !recursion_limit. value_within_limit ( self . depth ) {
342
- self . selcx . infcx . err_ctxt ( ) . report_overflow_error (
343
- OverflowCause :: DeeplyNormalize ( data. into ( ) ) ,
344
- self . cause . span ,
345
- false ,
346
- |diag| {
347
- diag. note ( crate :: fluent_generated:: trait_selection_ty_alias_overflow) ;
348
- } ,
349
- ) ;
350
- }
351
-
352
- let infcx = self . selcx . infcx ;
353
- self . obligations . extend (
354
- infcx. tcx . predicates_of ( data. def_id ) . instantiate_own ( infcx. tcx , data. args ) . map (
355
- |( mut predicate, span) | {
356
- if data. has_escaping_bound_vars ( ) {
357
- ( predicate, ..) = BoundVarReplacer :: replace_bound_vars (
358
- infcx,
359
- & mut self . universes ,
360
- predicate,
361
- ) ;
362
- }
363
- let mut cause = self . cause . clone ( ) ;
364
- cause. map_code ( |code| {
365
- ObligationCauseCode :: TypeAlias ( code, span, data. def_id )
366
- } ) ;
367
- Obligation :: new ( infcx. tcx , cause, self . param_env , predicate)
368
- } ,
369
- ) ,
370
- ) ;
371
- self . depth += 1 ;
372
- let res = infcx
373
- . tcx
374
- . type_of ( data. def_id )
375
- . instantiate ( infcx. tcx , data. args )
376
- . fold_with ( self ) ;
377
- self . depth -= 1 ;
378
- res
379
- }
380
-
381
- ty:: Inherent if !data. has_escaping_bound_vars ( ) => {
382
- // This branch is *mostly* just an optimization: when we don't
383
- // have escaping bound vars, we don't need to replace them with
384
- // placeholders (see branch below). *Also*, we know that we can
385
- // register an obligation to *later* project, since we know
386
- // there won't be bound vars there.
387
-
388
- let data = data. fold_with ( self ) ;
389
-
390
- project:: normalize_inherent_projection (
391
- self . selcx ,
392
- self . param_env ,
393
- data,
394
- self . cause . clone ( ) ,
395
- self . depth ,
396
- self . obligations ,
397
- )
398
- }
399
-
400
- ty:: Inherent => {
401
- let infcx = self . selcx . infcx ;
402
- let ( data, mapped_regions, mapped_types, mapped_consts) =
403
- BoundVarReplacer :: replace_bound_vars ( infcx, & mut self . universes , data) ;
404
- let data = data. fold_with ( self ) ;
405
- let ty = project:: normalize_inherent_projection (
406
- self . selcx ,
407
- self . param_env ,
408
- data,
409
- self . cause . clone ( ) ,
410
- self . depth ,
411
- self . obligations ,
412
- ) ;
413
-
414
- PlaceholderReplacer :: replace_placeholders (
415
- infcx,
416
- mapped_regions,
417
- mapped_types,
418
- mapped_consts,
419
- & self . universes ,
420
- ty,
421
- )
422
- }
418
+ ty:: Projection => self . normalize_trait_projection ( data) ,
419
+ ty:: Free => self . normalize_free_alias ( data) ,
420
+ ty:: Inherent => self . normalize_inherent_projection ( data) ,
423
421
}
424
422
}
425
423
0 commit comments