@@ -635,13 +635,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
635
635
636
636
#[ instrument( skip( self ) , level = "debug" ) ]
637
637
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 ( ) {
639
640
constant
640
641
} else {
641
642
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
+ )
645
650
}
646
651
}
647
652
@@ -671,6 +676,41 @@ pub struct BoundVarReplacer<'me, 'tcx> {
671
676
universe_indices : & ' me mut Vec < Option < ty:: UniverseIndex > > ,
672
677
}
673
678
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
+
674
714
impl < ' me , ' tcx > BoundVarReplacer < ' me , ' tcx > {
675
715
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
676
716
/// use a binding level above `universe_indices.len()`, we fail.
0 commit comments