From afa884c03a90f4d773e28faaad4bc7845d677332 Mon Sep 17 00:00:00 2001
From: scalexm <alexandre@scalexm.fr>
Date: Thu, 1 Nov 2018 15:30:37 +0100
Subject: [PATCH] Instantiate all bound vars existentially

---
 src/librustc/infer/canonical/substitute.rs    |  2 +-
 src/librustc/infer/higher_ranked/mod.rs       | 10 +++----
 src/librustc/infer/mod.rs                     | 12 ++++----
 src/librustc/traits/error_reporting.rs        |  5 ++--
 src/librustc/ty/fold.rs                       | 30 +++++++++----------
 .../nll/type_check/input_output.rs            |  2 +-
 .../borrow_check/nll/type_check/mod.rs        |  2 +-
 src/librustc_traits/chalk_context/mod.rs      |  7 ++---
 src/librustc_typeck/check/callee.rs           | 11 +++----
 src/librustc_typeck/check/closure.rs          |  4 +--
 src/librustc_typeck/check/compare_method.rs   | 11 +++----
 src/librustc_typeck/check/method/confirm.rs   | 12 ++++----
 src/librustc_typeck/check/method/mod.rs       |  8 +++--
 src/librustc_typeck/check/method/probe.rs     |  7 +++--
 src/librustc_typeck/check/mod.rs              | 10 +++----
 15 files changed, 68 insertions(+), 65 deletions(-)

diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc/infer/canonical/substitute.rs
index b8c1ed236c0..70ce5d0d8dc 100644
--- a/src/librustc/infer/canonical/substitute.rs
+++ b/src/librustc/infer/canonical/substitute.rs
@@ -80,6 +80,6 @@ where
             }
         };
 
-        tcx.replace_escaping_bound_vars(value, fld_r, fld_t)
+        tcx.replace_escaping_bound_vars(value, fld_r, fld_t).0
     }
 }
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index 3e08a4e021a..642382bcf0f 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -59,11 +59,11 @@ impl<'a, 'gcx, 'tcx> CombineFields<'a, 'gcx, 'tcx> {
             // with a fresh region variable. These region variables --
             // but no other pre-existing region variables -- can name
             // the placeholders.
-            let (a_prime, _) =
-                self.infcx.replace_late_bound_regions_with_fresh_var(
-                    span,
-                    HigherRankedType,
-                    a);
+            let (a_prime, _) = self.infcx.replace_bound_vars_with_fresh_vars(
+                span,
+                HigherRankedType,
+                a
+            );
 
             debug!("a_prime={:?}", a_prime);
             debug!("b_prime={:?}", b_prime);
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index f5513acecf9..4ddf47c88dd 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1328,18 +1328,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.report_and_explain_type_error(trace, &err)
     }
 
-    pub fn replace_late_bound_regions_with_fresh_var<T>(
+    pub fn replace_bound_vars_with_fresh_vars<T>(
         &self,
         span: Span,
         lbrct: LateBoundRegionConversionTime,
-        value: &ty::Binder<T>,
+        value: &ty::Binder<T>
     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
     where
-        T: TypeFoldable<'tcx>,
+        T: TypeFoldable<'tcx>
     {
-        self.tcx.replace_late_bound_regions(value, |br| {
-            self.next_region_var(LateBoundRegion(span, br, lbrct))
-        })
+        let fld_r = |br| self.next_region_var(LateBoundRegion(span, br, lbrct));
+        let fld_t = |_| self.next_ty_var(TypeVariableOrigin::MiscVariable(span));
+        self.tcx.replace_bound_vars(value, fld_r, fld_t)
     }
 
     /// Given a higher-ranked projection predicate like:
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index fbada789956..2761a954cea 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -212,10 +212,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             // cause I have no idea for a good error message.
             if let ty::Predicate::Projection(ref data) = predicate {
                 let mut selcx = SelectionContext::new(self);
-                let (data, _) = self.replace_late_bound_regions_with_fresh_var(
+                let (data, _) = self.replace_bound_vars_with_fresh_vars(
                     obligation.cause.span,
                     infer::LateBoundRegionConversionTime::HigherRankedType,
-                    data);
+                    data
+                );
                 let mut obligations = vec![];
                 let normalized_ty = super::normalize_projection_type(
                     &mut selcx,
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index ffa4380a5d6..a897afa0ca6 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -520,22 +520,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn replace_late_bound_regions<T, F>(
         self,
         value: &Binder<T>,
-        mut fld_r: F
+        fld_r: F
     ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
               T: TypeFoldable<'tcx>
     {
-        let mut map = BTreeMap::new();
-        let mut real_fldr = |br| {
-            *map.entry(br).or_insert_with(|| fld_r(br))
-        };
-
         // identity for bound types
-        let mut fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
-
-        let mut replacer = BoundVarReplacer::new(self, &mut real_fldr, &mut fld_t);
-        let result = value.skip_binder().fold_with(&mut replacer);
-        (result, map)
+        let fld_t = |bound_ty| self.mk_ty(ty::Bound(bound_ty));
+        self.replace_escaping_bound_vars(value.skip_binder(), fld_r, fld_t)
     }
 
     /// Replace all escaping bound vars. The `fld_r` closure replaces escaping
@@ -545,17 +537,23 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         value: &T,
         mut fld_r: F,
         mut fld_t: G
-    ) -> T
+    ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
               G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
               T: TypeFoldable<'tcx>
     {
+        let mut map = BTreeMap::new();
+
         if !value.has_escaping_bound_vars() {
-            value.clone()
+            (value.clone(), map)
         } else {
-            let mut replacer = BoundVarReplacer::new(self, &mut fld_r, &mut fld_t);
+            let mut real_fld_r = |br| {
+                *map.entry(br).or_insert_with(|| fld_r(br))
+            };
+
+            let mut replacer = BoundVarReplacer::new(self, &mut real_fld_r, &mut fld_t);
             let result = value.fold_with(&mut replacer);
-            result
+            (result, map)
         }
     }
 
@@ -567,7 +565,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         value: &Binder<T>,
         fld_r: F,
         fld_t: G
-    ) -> T
+    ) -> (T, BTreeMap<ty::BoundRegion, ty::Region<'tcx>>)
         where F: FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
               G: FnMut(ty::BoundTy) -> ty::Ty<'tcx>,
               T: TypeFoldable<'tcx>
diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
index ab4ee3a4ad0..85ea39e538f 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs
@@ -62,7 +62,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     // "inside" the closure.
                     Some(
                         self.infcx
-                            .replace_late_bound_regions_with_fresh_var(
+                            .replace_bound_vars_with_fresh_vars(
                                 mir.span,
                                 LateBoundRegionConversionTime::FnCall,
                                 &poly_sig,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index c8d2bcd8b93..2193dba9fca 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -1406,7 +1406,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                         return;
                     }
                 };
-                let (sig, map) = self.infcx.replace_late_bound_regions_with_fresh_var(
+                let (sig, map) = self.infcx.replace_bound_vars_with_fresh_vars(
                     term.source_info.span,
                     LateBoundRegionConversionTime::FnCall,
                     &sig,
diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs
index 611cace45df..0fd9f607a54 100644
--- a/src/librustc_traits/chalk_context/mod.rs
+++ b/src/librustc_traits/chalk_context/mod.rs
@@ -347,12 +347,11 @@ impl context::UnificationOps<ChalkArenas<'gcx>, ChalkArenas<'tcx>>
         &mut self,
         arg: &ty::Binder<Goal<'tcx>>,
     ) -> Goal<'tcx> {
-        let (value, _map) = self.infcx.replace_late_bound_regions_with_fresh_var(
+        self.infcx.replace_bound_vars_with_fresh_vars(
             DUMMY_SP,
             LateBoundRegionConversionTime::HigherRankedType,
-            arg,
-        );
-        value
+            arg
+        ).0
     }
 
     fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box<dyn Debug + 'v> {
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index de4293aaaea..411583b36b9 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -110,10 +110,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 // fnmut vs fnonce. If so, we have to defer further processing.
                 if self.closure_kind(def_id, substs).is_none() {
                     let closure_ty = self.closure_sig(def_id, substs);
-                    let fn_sig = self.replace_late_bound_regions_with_fresh_var(call_expr.span,
-                                                                   infer::FnCall,
-                                                                   &closure_ty)
-                        .0;
+                    let fn_sig = self.replace_bound_vars_with_fresh_vars(
+                        call_expr.span,
+                        infer::FnCall,
+                        &closure_ty
+                    ).0;
                     let adjustments = autoderef.adjust_steps(Needs::None);
                     self.record_deferred_call_resolution(def_id, DeferredCallResolution {
                         call_expr,
@@ -284,7 +285,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // previously appeared within a `Binder<>` and hence would not
         // have been normalized before.
         let fn_sig =
-            self.replace_late_bound_regions_with_fresh_var(call_expr.span, infer::FnCall, &fn_sig)
+            self.replace_bound_vars_with_fresh_vars(call_expr.span, infer::FnCall, &fn_sig)
                 .0;
         let fn_sig = self.normalize_associated_types_in(call_expr.span, &fn_sig);
 
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 010561d1001..10ac2448d00 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -564,7 +564,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             // `liberated_sig` is E'.
             {
                 // Instantiate (this part of..) S to S', i.e., with fresh variables.
-                let (supplied_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+                let (supplied_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
                     hir_ty.span,
                     LateBoundRegionConversionTime::FnCall,
                     &ty::Binder::bind(supplied_ty),
@@ -605,7 +605,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                 );
             }
 
-            let (supplied_output_ty, _) = self.infcx.replace_late_bound_regions_with_fresh_var(
+            let (supplied_output_ty, _) = self.infcx.replace_bound_vars_with_fresh_vars(
                 decl.output.span(),
                 LateBoundRegionConversionTime::FnCall,
                 &supplied_sig.output(),
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 45c5457c9e1..e30ebe07e54 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -233,7 +233,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         let mut selcx = traits::SelectionContext::new(&infcx);
 
         let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_skol_substs);
-        let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var(
+        let (impl_m_own_bounds, _) = infcx.replace_bound_vars_with_fresh_vars(
             impl_m_span,
             infer::HigherRankedType,
             &ty::Binder::bind(impl_m_own_bounds.predicates)
@@ -262,10 +262,11 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         // Compute placeholder form of impl and trait method tys.
         let tcx = infcx.tcx;
 
-        let (impl_sig, _) =
-            infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
-                                                            infer::HigherRankedType,
-                                                            &tcx.fn_sig(impl_m.def_id));
+        let (impl_sig, _) = infcx.replace_bound_vars_with_fresh_vars(
+            impl_m_span,
+            infer::HigherRankedType,
+            &tcx.fn_sig(impl_m.def_id)
+        );
         let impl_sig =
             inh.normalize_associated_types_in(impl_m_span,
                                               impl_m_node_id,
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 75f5bf74c6a..5144f3e41d4 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -245,7 +245,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
                     let original_poly_trait_ref = principal.with_self_ty(this.tcx, object_ty);
                     let upcast_poly_trait_ref = this.upcast(original_poly_trait_ref, trait_def_id);
                     let upcast_trait_ref =
-                        this.replace_late_bound_regions_with_fresh_var(&upcast_poly_trait_ref);
+                        this.replace_bound_vars_with_fresh_vars(&upcast_poly_trait_ref);
                     debug!("original_poly_trait_ref={:?} upcast_trait_ref={:?} target_trait={:?}",
                            original_poly_trait_ref,
                            upcast_trait_ref,
@@ -268,7 +268,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
             probe::WhereClausePick(ref poly_trait_ref) => {
                 // Where clauses can have bound regions in them. We need to instantiate
                 // those to convert from a poly-trait-ref to a trait-ref.
-                self.replace_late_bound_regions_with_fresh_var(&poly_trait_ref).substs
+                self.replace_bound_vars_with_fresh_vars(&poly_trait_ref).substs
             }
         }
     }
@@ -398,7 +398,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         // NB: Instantiate late-bound regions first so that
         // `instantiate_type_scheme` can normalize associated types that
         // may reference those regions.
-        let method_sig = self.replace_late_bound_regions_with_fresh_var(&sig);
+        let method_sig = self.replace_bound_vars_with_fresh_vars(&sig);
         debug!("late-bound lifetimes from method instantiated, method_sig={:?}",
                method_sig);
 
@@ -633,11 +633,9 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
         upcast_trait_refs.into_iter().next().unwrap()
     }
 
-    fn replace_late_bound_regions_with_fresh_var<T>(&self, value: &ty::Binder<T>) -> T
+    fn replace_bound_vars_with_fresh_vars<T>(&self, value: &ty::Binder<T>) -> T
         where T: TypeFoldable<'tcx>
     {
-        self.fcx
-            .replace_late_bound_regions_with_fresh_var(self.span, infer::FnCall, value)
-            .0
+        self.fcx.replace_bound_vars_with_fresh_vars(self.span, infer::FnCall, value).0
     }
 }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 637f3eaae9a..ac338ba6678 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -311,9 +311,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
         // `instantiate_type_scheme` can normalize associated types that
         // may reference those regions.
         let fn_sig = tcx.fn_sig(def_id);
-        let fn_sig = self.replace_late_bound_regions_with_fresh_var(span,
-                                                                    infer::FnCall,
-                                                                    &fn_sig).0;
+        let fn_sig = self.replace_bound_vars_with_fresh_vars(
+            span,
+            infer::FnCall,
+            &fn_sig
+        ).0;
         let fn_sig = fn_sig.subst(self.tcx, substs);
         let fn_sig = match self.normalize_associated_types_in_as_infer_ok(span, &fn_sig) {
             InferOk { value, obligations: o } => {
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 305efd0d75a..4c06cae1d07 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -755,8 +755,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
                 self.probe(|_| {
                     let substs = self.fresh_substs_for_item(self.span, method.def_id);
                     let fty = fty.subst(self.tcx, substs);
-                    let (fty, _) = self.replace_late_bound_regions_with_fresh_var(
-                        self.span, infer::FnCall, &fty);
+                    let (fty, _) = self.replace_bound_vars_with_fresh_vars(
+                        self.span,
+                        infer::FnCall,
+                        &fty
+                    );
 
                     if let Some(self_ty) = self_ty {
                         if self.at(&ObligationCause::dummy(), self.param_env)
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 2e6797ef23a..41e0c6c0a19 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -1921,11 +1921,11 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
                                         poly_trait_ref: ty::PolyTraitRef<'tcx>)
                                         -> Ty<'tcx>
     {
-        let (trait_ref, _) =
-            self.replace_late_bound_regions_with_fresh_var(
-                span,
-                infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
-                &poly_trait_ref);
+        let (trait_ref, _) = self.replace_bound_vars_with_fresh_vars(
+            span,
+            infer::LateBoundRegionConversionTime::AssocTypeProjection(item_def_id),
+            &poly_trait_ref
+        );
 
         self.tcx().mk_projection(item_def_id, trait_ref.substs)
     }