@@ -635,13 +635,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
635635
636636 #[ instrument( skip( self ) , level = "debug" ) ]
637637 fn fold_const ( & mut self , constant : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
638- if self . selcx . tcx ( ) . lazy_normalization ( ) || !self . eager_inference_replacement {
638+ let tcx = self . selcx . tcx ( ) ;
639+ if tcx. lazy_normalization ( ) {
639640 constant
640641 } else {
641642 let constant = constant. super_fold_with ( self ) ;
642- debug ! ( ?constant) ;
643- debug ! ( "self.param_env: {:?}" , self . param_env) ;
644- constant. eval ( self . selcx . tcx ( ) , self . param_env )
643+ debug ! ( ?constant, ?self . param_env) ;
644+ with_replaced_escaping_bound_vars (
645+ self . selcx . infcx ( ) ,
646+ & mut self . universes ,
647+ constant,
648+ |constant| constant. eval ( tcx, self . param_env ) ,
649+ )
645650 }
646651 }
647652
@@ -671,6 +676,41 @@ pub struct BoundVarReplacer<'me, 'tcx> {
671676 universe_indices : & ' me mut Vec < Option < ty:: UniverseIndex > > ,
672677}
673678
679+ /// Executes `f` on `value` after replacing all escaping bound variables with placeholders
680+ /// and then replaces these placeholders with the original bound variables in the result.
681+ ///
682+ /// In most places, bound variables should be replaced right when entering a binder, making
683+ /// this function unnecessary. However, normalization currently does not do that, so we have
684+ /// to do this lazily.
685+ ///
686+ /// You should not add any additional uses of this function, at least not without first
687+ /// discussing it with t-types.
688+ ///
689+ /// FIXME(@lcnr): We may even consider experimenting with eagerly replacing bound vars during
690+ /// normalization as well, at which point this function will be unnecessary and can be removed.
691+ pub fn with_replaced_escaping_bound_vars < ' a , ' tcx , T : TypeFoldable < ' tcx > , R : TypeFoldable < ' tcx > > (
692+ infcx : & ' a InferCtxt < ' a , ' tcx > ,
693+ universe_indices : & ' a mut Vec < Option < ty:: UniverseIndex > > ,
694+ value : T ,
695+ f : impl FnOnce ( T ) -> R ,
696+ ) -> R {
697+ if value. has_escaping_bound_vars ( ) {
698+ let ( value, mapped_regions, mapped_types, mapped_consts) =
699+ BoundVarReplacer :: replace_bound_vars ( infcx, universe_indices, value) ;
700+ let result = f ( value) ;
701+ PlaceholderReplacer :: replace_placeholders (
702+ infcx,
703+ mapped_regions,
704+ mapped_types,
705+ mapped_consts,
706+ universe_indices,
707+ result,
708+ )
709+ } else {
710+ f ( value)
711+ }
712+ }
713+
674714impl < ' me , ' tcx > BoundVarReplacer < ' me , ' tcx > {
675715 /// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
676716 /// use a binding level above `universe_indices.len()`, we fail.
0 commit comments