@@ -10,8 +10,8 @@ use rustc_macros::extension;
1010use rustc_middle:: span_bug;
1111use rustc_middle:: traits:: { ObligationCause , ObligationCauseCode } ;
1212use 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 ,
1515} ;
1616use tracing:: { debug, instrument} ;
1717
@@ -178,6 +178,163 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
178178
179179 if !needs_normalization ( self . selcx . infcx , & value) { value } else { value. fold_with ( self ) }
180180 }
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+ }
181338}
182339
183340impl < ' 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
258415 }
259416 }
260417 }
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) ,
423421 }
424422 }
425423
0 commit comments