@@ -295,6 +295,32 @@ where
295295 result
296296}
297297
298+ #[ instrument( level = "info" , skip( selcx, param_env, cause, obligations) ) ]
299+ pub fn try_normalize_with_depth_to < ' a , ' b , ' tcx , T > (
300+ selcx : & ' a mut SelectionContext < ' b , ' tcx > ,
301+ param_env : ty:: ParamEnv < ' tcx > ,
302+ cause : ObligationCause < ' tcx > ,
303+ depth : usize ,
304+ value : T ,
305+ obligations : & mut Vec < PredicateObligation < ' tcx > > ,
306+ ) -> T
307+ where
308+ T : TypeFoldable < ' tcx > ,
309+ {
310+ debug ! ( obligations. len = obligations. len( ) ) ;
311+ let mut normalizer = AssocTypeNormalizer :: new_without_eager_inference_replacement (
312+ selcx,
313+ param_env,
314+ cause,
315+ depth,
316+ obligations,
317+ ) ;
318+ let result = ensure_sufficient_stack ( || normalizer. fold ( value) ) ;
319+ debug ! ( ?result, obligations. len = normalizer. obligations. len( ) ) ;
320+ debug ! ( ?normalizer. obligations, ) ;
321+ result
322+ }
323+
298324pub ( crate ) fn needs_normalization < ' tcx , T : TypeFoldable < ' tcx > > ( value : & T , reveal : Reveal ) -> bool {
299325 match reveal {
300326 Reveal :: UserFacing => value
@@ -314,6 +340,10 @@ struct AssocTypeNormalizer<'a, 'b, 'tcx> {
314340 obligations : & ' a mut Vec < PredicateObligation < ' tcx > > ,
315341 depth : usize ,
316342 universes : Vec < Option < ty:: UniverseIndex > > ,
343+ /// If true, when a projection is unable to be completed, an inference
344+ /// variable will be created and an obligation registered to project to that
345+ /// inference variable. Also, constants will be eagerly evaluated.
346+ eager_inference_replacement : bool ,
317347}
318348
319349impl < ' a , ' b , ' tcx > AssocTypeNormalizer < ' a , ' b , ' tcx > {
@@ -324,7 +354,33 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> {
324354 depth : usize ,
325355 obligations : & ' a mut Vec < PredicateObligation < ' tcx > > ,
326356 ) -> AssocTypeNormalizer < ' a , ' b , ' tcx > {
327- AssocTypeNormalizer { selcx, param_env, cause, obligations, depth, universes : vec ! [ ] }
357+ AssocTypeNormalizer {
358+ selcx,
359+ param_env,
360+ cause,
361+ obligations,
362+ depth,
363+ universes : vec ! [ ] ,
364+ eager_inference_replacement : true ,
365+ }
366+ }
367+
368+ fn new_without_eager_inference_replacement (
369+ selcx : & ' a mut SelectionContext < ' b , ' tcx > ,
370+ param_env : ty:: ParamEnv < ' tcx > ,
371+ cause : ObligationCause < ' tcx > ,
372+ depth : usize ,
373+ obligations : & ' a mut Vec < PredicateObligation < ' tcx > > ,
374+ ) -> AssocTypeNormalizer < ' a , ' b , ' tcx > {
375+ AssocTypeNormalizer {
376+ selcx,
377+ param_env,
378+ cause,
379+ obligations,
380+ depth,
381+ universes : vec ! [ ] ,
382+ eager_inference_replacement : false ,
383+ }
328384 }
329385
330386 fn fold < T : TypeFoldable < ' tcx > > ( & mut self , value : T ) -> T {
@@ -428,14 +484,28 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
428484 // there won't be bound vars there.
429485
430486 let data = data. super_fold_with ( self ) ;
431- let normalized_ty = normalize_projection_type (
432- self . selcx ,
433- self . param_env ,
434- data,
435- self . cause . clone ( ) ,
436- self . depth ,
437- & mut self . obligations ,
438- ) ;
487+ let normalized_ty = if self . eager_inference_replacement {
488+ normalize_projection_type (
489+ self . selcx ,
490+ self . param_env ,
491+ data,
492+ self . cause . clone ( ) ,
493+ self . depth ,
494+ & mut self . obligations ,
495+ )
496+ } else {
497+ opt_normalize_projection_type (
498+ self . selcx ,
499+ self . param_env ,
500+ data,
501+ self . cause . clone ( ) ,
502+ self . depth ,
503+ & mut self . obligations ,
504+ )
505+ . ok ( )
506+ . flatten ( )
507+ . unwrap_or_else ( || ty:: Term :: Ty ( ty. super_fold_with ( self ) ) )
508+ } ;
439509 debug ! (
440510 ?self . depth,
441511 ?ty,
@@ -501,7 +571,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
501571 }
502572
503573 fn fold_const ( & mut self , constant : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
504- if self . selcx . tcx ( ) . lazy_normalization ( ) {
574+ if self . selcx . tcx ( ) . lazy_normalization ( ) || ! self . eager_inference_replacement {
505575 constant
506576 } else {
507577 let constant = constant. super_fold_with ( self ) ;
0 commit comments