From 6947948b4df98b82a9e8f6847db442921edfc37b Mon Sep 17 00:00:00 2001
From: Jared Roesch <roeschinc@gmail.com>
Date: Fri, 26 Jun 2015 12:23:41 -0700
Subject: [PATCH] Move FufillmentContext into InferContext

---
 src/librustc/middle/infer/mod.rs            | 13 ++++++++++-
 src/librustc/middle/traits/mod.rs           |  2 +-
 src/librustc_trans/trans/common.rs          |  4 ++--
 src/librustc_trans/trans/monomorphize.rs    |  2 +-
 src/librustc_typeck/check/closure.rs        |  2 +-
 src/librustc_typeck/check/compare_method.rs |  4 ++--
 src/librustc_typeck/check/dropck.rs         |  2 +-
 src/librustc_typeck/check/mod.rs            | 25 ++++++++++++---------
 src/librustc_typeck/check/regionck.rs       | 12 ++++++----
 src/librustc_typeck/coherence/mod.rs        |  5 +++--
 src/librustc_typeck/coherence/overlap.rs    |  2 +-
 src/librustc_typeck/collect.rs              |  2 +-
 src/librustc_typeck/lib.rs                  |  2 +-
 13 files changed, 48 insertions(+), 29 deletions(-)

diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index c355e8b82a6..4617d3860a3 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -87,6 +87,8 @@ pub struct InferCtxt<'a, 'tcx: 'a> {
 
     pub parameter_environment: ty::ParameterEnvironment<'a, 'tcx>,
 
+    pub fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
+
     // This is a temporary field used for toggling on normalization in the inference context,
     // as we move towards the approach described here:
     // https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293
@@ -327,9 +329,16 @@ pub fn fixup_err_to_string(f: fixup_err) -> String {
     }
 }
 
+/// errors_will_be_reported is required to proxy to the fulfillment context
+/// FIXME -- a better option would be to hold back on modifying
+/// the global cache until we know that all dependent obligations
+/// are also satisfied. In that case, we could actually remove
+/// this boolean flag, and we'd also avoid the problem of squelching
+/// duplicate errors that occur across fns.
 pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
                                 tables: &'a RefCell<ty::Tables<'tcx>>,
-                                param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>)
+                                param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>,
+                                errors_will_be_reported: bool)
                                 -> InferCtxt<'a, 'tcx> {
     InferCtxt {
         tcx: tcx,
@@ -339,6 +348,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
         float_unification_table: RefCell::new(UnificationTable::new()),
         region_vars: RegionVarBindings::new(tcx),
         parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()),
+        fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)),
         normalize: false,
         err_count_on_creation: tcx.sess.err_count()
     }
@@ -1009,6 +1019,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         raw_ty.adjust(self.tcx,
                       expr.span,
                       expr.id,
+                      raw_ty,
                       adjustment,
                       |method_call| self.tables
                                         .borrow()
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index 9df6ed5d681..c5afb7dd3db 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -397,7 +397,7 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
 
     let elaborated_env = unnormalized_env.with_caller_bounds(predicates);
 
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env));
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, Some(elaborated_env), false);
     let predicates = match fully_normalize(&infcx, &infcx.parameter_environment, cause,
                                            &infcx.parameter_environment.caller_bounds) {
         Ok(predicates) => predicates,
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 9c2aea1e67a..32a1f74063b 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -957,7 +957,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            trait_ref, trait_ref.def_id());
 
     tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
 
     // Do the initial selection for the obligation. This yields the
     // shallow result we are looking for -- that is, what specific impl.
@@ -1019,7 +1019,7 @@ pub fn normalize_and_test_predicates<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            predicates);
 
     let tcx = ccx.tcx();
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+    let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
     let typer = NormalizingClosureTyper::new(tcx);
     let mut selcx = traits::SelectionContext::new(&infcx, &typer);
     let mut fulfill_cx = traits::FulfillmentContext::new(false);
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index 67ccf64621a..6ad164719cf 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -324,7 +324,7 @@ pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
     // FIXME(#20304) -- cache
     // NOTE: @jroesch
     // Here is of an example where we do not use a param_env but use a typer instead.
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
     let typer = NormalizingClosureTyper::new(tcx);
     let mut selcx = traits::SelectionContext::new(&infcx, &typer);
     let cause = traits::ObligationCause::dummy();
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index b5ee46ece94..6d1e9dfacf2 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -125,7 +125,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
     expected_vid: ty::TyVid)
     -> (Option<ty::FnSig<'tcx>>, Option<ty::ClosureKind>)
 {
-    let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
+    let fulfillment_cx = fcx.inh.infcx.fulfillment_cx.borrow();
     // Here `expected_ty` is known to be a type inference variable.
 
     let expected_sig =
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index f62411e8582..6375926298f 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -43,7 +43,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
            impl_trait_ref);
 
-    let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+    let mut infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
     let mut fulfillment_cx = traits::FulfillmentContext::new(true);
 
     let trait_to_impl_substs = &impl_trait_ref.substs;
@@ -419,7 +419,7 @@ pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
     debug!("compare_const_impl(impl_trait_ref={:?})",
            impl_trait_ref);
 
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, true);
     let mut fulfillment_cx = traits::FulfillmentContext::new(true);
 
     // The below is for the most part highly similar to the procedure
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 6f0fbfebf46..7d911cf8b03 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -93,7 +93,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
                          ty: named_type } =
         tcx.lookup_item_type(self_type_did);
 
-    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+    let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
 
     infcx.commit_if_ok(|snapshot| {
         let (named_type_to_skolem, skol_map) =
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 2db1598db4b..76286cfe9ba 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -159,7 +159,7 @@ pub struct Inherited<'a, 'tcx: 'a> {
     fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
 
     // Tracks trait obligations incurred during this function body.
-    fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
+    // fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
 
     // When we process a call like `c()` where `c` is a closure type,
     // we may not have decided yet whether `c` is a `Fn`, `FnMut`, or
@@ -295,11 +295,11 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
            -> Inherited<'a, 'tcx> {
 
         Inherited {
-            infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env)),
+            // I'm probably screwed here ... more boolean prop ... 
+            infcx: infer::new_infer_ctxt(tcx, tables, Some(param_env), false),
             locals: RefCell::new(NodeMap()),
             tables: tables,
             fn_sig_map: RefCell::new(NodeMap()),
-            fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(true)),
             deferred_call_resolutions: RefCell::new(DefIdMap()),
             deferred_cast_checks: RefCell::new(Vec::new()),
         }
@@ -313,7 +313,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
                                         -> T
         where T : TypeFoldable<'tcx> + HasTypeFlags
     {
-        let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
+        let mut fulfillment_cx = self.infcx.fulfillment_cx.borrow_mut();
         assoc::normalize_associated_types_in(&self.infcx,
                                              typer,
                                              &mut *fulfillment_cx, span,
@@ -1389,7 +1389,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let cause = traits::ObligationCause::new(span,
                                                  self.body_id,
                                                  traits::ObligationCauseCode::MiscObligation);
-        self.inh.fulfillment_cx
+        self.inh
+            .infcx
+            .fulfillment_cx
             .borrow_mut()
             .normalize_projection_type(self.infcx(),
                                        self.infcx(),
@@ -1513,7 +1515,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                   builtin_bound: ty::BuiltinBound,
                                   cause: traits::ObligationCause<'tcx>)
     {
-        self.inh.fulfillment_cx.borrow_mut()
+        self.inh.infcx.fulfillment_cx.borrow_mut()
             .register_builtin_bound(self.infcx(), ty, builtin_bound, cause);
     }
 
@@ -1522,7 +1524,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     {
         debug!("register_predicate({:?})",
                obligation);
-        self.inh.fulfillment_cx
+        self.inh.infcx.fulfillment_cx
             .borrow_mut()
             .register_predicate_obligation(self.infcx(), obligation);
     }
@@ -1558,6 +1560,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let raw_ty = self.infcx().shallow_resolve(raw_ty);
         let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
         raw_ty.adjust(self.tcx(), expr.span, expr.id, adjustment, |method_call| {
+                                                   .method_map
             self.inh.tables.borrow().method_map.get(&method_call)
                                         .map(|method| resolve_ty(method.ty))
         })
@@ -1648,7 +1651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                       region: ty::Region,
                                       cause: traits::ObligationCause<'tcx>)
     {
-        let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
+        let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
         fulfillment_cx.register_region_obligation(ty, region, cause);
     }
 
@@ -1747,7 +1750,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
 
         self.select_all_obligations_and_apply_defaults();
-        let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
+        let mut fulfillment_cx = self.inh.infcx.fulfillment_cx.borrow_mut();
         match fulfillment_cx.select_all_or_error(self.infcx(), self.infcx()) {
             Ok(()) => { }
             Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
@@ -1757,7 +1760,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Select as many obligations as we can at present.
     fn select_obligations_where_possible(&self) {
         match
-            self.inh.fulfillment_cx
+            self.inh.infcx.fulfillment_cx
             .borrow_mut()
             .select_where_possible(self.infcx(), self.infcx())
         {
@@ -1772,7 +1775,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// work.
     fn select_new_obligations(&self) {
         match
-            self.inh.fulfillment_cx
+            self.inh.infcx.fulfillment_cx
             .borrow_mut()
             .select_new_obligations(self.infcx(), self.infcx())
         {
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index a8630190738..661e1856ce8 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -318,9 +318,13 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
         // Make a copy of the region obligations vec because we'll need
         // to be able to borrow the fulfillment-cx below when projecting.
         let region_obligations =
-            self.fcx.inh.fulfillment_cx.borrow()
-                                       .region_obligations(node_id)
-                                       .to_vec();
+            self.fcx
+                .inh
+                .infcx
+                .fulfillment_cx
+                .borrow()
+                .region_obligations(node_id)
+                .to_vec();
 
         for r_o in &region_obligations {
             debug!("visit_region_obligations: r_o={:?}",
@@ -332,7 +336,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
 
         // Processing the region obligations should not cause the list to grow further:
         assert_eq!(region_obligations.len(),
-                   self.fcx.inh.fulfillment_cx.borrow().region_obligations(node_id).len());
+                   self.fcx.inh.infcx.fulfillment_cx.borrow().region_obligations(node_id).len());
     }
 
     /// This method populates the region map's `free_region_map`. It walks over the transformed
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index fbabc287342..23336c43995 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -448,7 +448,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (free)",
                    source, target);
 
-            let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env));
+            let infcx = new_infer_ctxt(tcx, &tcx.tables, Some(param_env), true);
 
             let check_mutbl = |mt_a: ty::mt<'tcx>, mt_b: ty::mt<'tcx>,
                                mk_ptr: &Fn(Ty<'tcx>) -> Ty<'tcx>| {
@@ -632,7 +632,8 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
 pub fn check_coherence(crate_context: &CrateCtxt) {
     CoherenceChecker {
         crate_context: crate_context,
-        inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None),
+        // XXXJAREDXXX: not sure if the bool is right here?
+        inference_context: new_infer_ctxt(crate_context.tcx, &crate_context.tcx.tables, None, false),
         inherent_impls: RefCell::new(FnvHashMap()),
     }.check(crate_context.tcx.map.krate());
     unsafety::check(crate_context.tcx);
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index 3495714fcc7..42c6bcbfbb9 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -133,7 +133,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
                    impl1_def_id,
                    impl2_def_id);
 
-            let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None);
+            let infcx = infer::new_infer_ctxt(self.tcx, &self.tcx.tables, None, false);
             if traits::overlapping_impls(&infcx, impl1_def_id, impl2_def_id) {
                 self.report_overlap_error(trait_def_id, impl1_def_id, impl2_def_id);
             }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 7909908079f..c45fbb70002 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -2211,7 +2211,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
                base_type,
                base_type_free);
 
-        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+        let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
         drop(::require_same_types(tcx,
                                   Some(&infcx),
                                   false,
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 48a64675c70..8c3ef4ae631 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -188,7 +188,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
 {
     let result = match maybe_infcx {
         None => {
-            let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None);
+            let infcx = infer::new_infer_ctxt(tcx, &tcx.tables, None, false);
             infer::mk_eqty(&infcx, t1_is_expected, infer::Misc(span), t1, t2)
         }
         Some(infcx) => {