about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-07 06:02:08 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-06-26 10:31:49 -0400
commit6ac89174b8b1f75ff867588e82a51e7134aaba31 (patch)
treee00f96864d94d19a6e5ca388b9784e849e410ec0
parentefc84c83f91e405830aea88ecab2a2495dd9e1db (diff)
downloadrust-6ac89174b8b1f75ff867588e82a51e7134aaba31.tar.gz
rust-6ac89174b8b1f75ff867588e82a51e7134aaba31.zip
mk `fully_perform_op_and_get_region_constraint_data` a TypeOp method
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/liveness.rs11
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs63
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/type_op/mod.rs64
3 files changed, 82 insertions, 56 deletions
diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
index 2640082c7cf..9c854e38cc5 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use borrow_check::nll::region_infer::Cause;
-use borrow_check::nll::type_check::type_op::DropckOutlives;
+use borrow_check::nll::type_check::type_op::{DropckOutlives, TypeOp};
 use borrow_check::nll::type_check::AtLocation;
 use dataflow::move_paths::{HasMoveData, MoveData};
 use dataflow::MaybeInitializedPlaces;
@@ -218,10 +218,15 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
 
         let param_env = cx.param_env;
         let (dropped_kinds, region_constraint_data) =
-            cx.fully_perform_op_and_get_region_constraint_data(DropckOutlives::new(
+            DropckOutlives::new(
                 param_env,
                 dropped_ty,
-            )).unwrap();
+            ).fully_perform(
+                cx.infcx,
+                cx.region_bound_pairs,
+                cx.implicit_region_bound,
+                cx.param_env,
+            ).unwrap();
 
         DropData {
             dropped_kinds,
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 f81b56de248..e2f6ad0bde3 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -21,12 +21,12 @@ use dataflow::FlowAtLocation;
 use dataflow::MaybeInitializedPlaces;
 use rustc::hir::def_id::DefId;
 use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
-use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, UnitResult};
+use rustc::infer::{InferCtxt, LateBoundRegionConversionTime, UnitResult};
 use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor};
 use rustc::mir::*;
-use rustc::traits::{ObligationCause, TraitEngine};
+use rustc::traits::ObligationCause;
 use rustc::ty::error::TypeError;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
@@ -733,18 +733,18 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         locations: Locations,
         op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
     ) -> Result<R, TypeError<'tcx>> {
-        match op.trivial_noop() {
-            Ok(r) => Ok(r),
-            Err(op) => {
-                let (r, opt_data) = self.fully_perform_op_and_get_region_constraint_data(op)?;
-
-                if let Some(data) = opt_data {
-                    self.push_region_constraints(locations, data);
-                }
+        let (r, opt_data) = op.fully_perform(
+            self.infcx,
+            self.region_bound_pairs,
+            self.implicit_region_bound,
+            self.param_env,
+        )?;
 
-                Ok(r)
-            }
+        if let Some(data) = opt_data {
+            self.push_region_constraints(locations, data);
         }
+
+        Ok(r)
     }
 
     fn push_region_constraints(
@@ -769,45 +769,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         }
     }
 
-    /// Helper for `fully_perform_op`, but also used on its own
-    /// sometimes to enable better caching: executes `op` fully (along
-    /// with resulting obligations) and returns the full set of region
-    /// obligations. If the same `op` were to be performed at some
-    /// other location, then the same set of region obligations would
-    /// be generated there, so this can be useful for caching.
-    fn fully_perform_op_and_get_region_constraint_data<R>(
-        &mut self,
-        op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
-    ) -> Result<(R, Option<Rc<RegionConstraintData<'tcx>>>), TypeError<'tcx>> {
-        if cfg!(debug_assertions) {
-            info!("fully_perform_op_and_get_region_constraint_data({:?})", op,);
-        }
-
-        let infcx = self.infcx;
-        let mut fulfill_cx = TraitEngine::new(infcx.tcx);
-        let dummy_body_id = ObligationCause::dummy().body_id;
-        let InferOk { value, obligations } = infcx.commit_if_ok(|_| op.perform(infcx))?;
-        debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
-        fulfill_cx.register_predicate_obligations(infcx, obligations);
-        if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
-            span_mirbug!(self, "", "errors selecting obligation: {:?}", e);
-        }
-
-        infcx.process_registered_region_obligations(
-            self.region_bound_pairs,
-            self.implicit_region_bound,
-            self.param_env,
-            dummy_body_id,
-        );
-
-        let data = infcx.take_and_reset_region_constraints();
-        if data.is_empty() {
-            Ok((value, None))
-        } else {
-            Ok((value, Some(Rc::new(data))))
-        }
-    }
-
     fn sub_types(
         &mut self,
         sub: Ty<'tcx>,
diff --git a/src/librustc_mir/borrow_check/nll/type_check/type_op/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/type_op/mod.rs
index 127841bec7c..c3801b4fbac 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/type_op/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/type_op/mod.rs
@@ -9,12 +9,16 @@
 // except according to those terms.
 
 use rustc::infer::{InferCtxt, InferOk, InferResult};
+use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
 use rustc::traits::query::NoSolution;
-use rustc::traits::{Normalized, Obligation, ObligationCause, PredicateObligation};
+use rustc::traits::{Normalized, Obligation, ObligationCause, PredicateObligation, TraitEngine};
+use rustc::ty::error::TypeError;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::Kind;
-use rustc::ty::{ParamEnv, Predicate, Ty};
+use rustc::ty::{self, ParamEnv, Predicate, Ty};
+use std::rc::Rc;
 use std::fmt;
+use syntax::codemap::DUMMY_SP;
 
 pub(super) trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
     type Output;
@@ -23,9 +27,65 @@ pub(super) trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
     /// produce the output, else returns `Err(self)` back.
     fn trivial_noop(self) -> Result<Self::Output, Self>;
 
+    /// Given an infcx, performs **the kernel** of the operation: this does the
+    /// key action and then, optionally, returns a set of obligations which must be proven.
+    ///
+    /// This method is not meant to be invoked directly: instead, one
+    /// should use `fully_perform`, which will take those resulting
+    /// obligations and prove them, and then process the combined
+    /// results into region obligations which are returned.
     fn perform(self, infcx: &InferCtxt<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output>;
+
+    /// Processes the operation and all resulting obligations,
+    /// returning the final result along with any region constraints
+    /// (they will be given over to the NLL region solver).
+    #[inline(never)]
+    fn fully_perform(
+        self,
+        infcx: &InferCtxt<'_, 'gcx, 'tcx>,
+        region_bound_pairs: &[(ty::Region<'tcx>, GenericKind<'tcx>)],
+        implicit_region_bound: Option<ty::Region<'tcx>>,
+        param_env: ParamEnv<'tcx>,
+    ) -> Result<(Self::Output, Option<Rc<RegionConstraintData<'tcx>>>), TypeError<'tcx>> {
+        let op = match self.trivial_noop() {
+            Ok(r) => return Ok((r, None)),
+            Err(op) => op,
+        };
+
+        if cfg!(debug_assertions) {
+            info!("fully_perform_op_and_get_region_constraint_data({:?})", op);
+        }
+
+        let mut fulfill_cx = TraitEngine::new(infcx.tcx);
+        let dummy_body_id = ObligationCause::dummy().body_id;
+        let InferOk { value, obligations } = infcx.commit_if_ok(|_| op.perform(infcx))?;
+        debug_assert!(obligations.iter().all(|o| o.cause.body_id == dummy_body_id));
+        fulfill_cx.register_predicate_obligations(infcx, obligations);
+        if let Err(e) = fulfill_cx.select_all_or_error(infcx) {
+            infcx.tcx.sess.diagnostic().delay_span_bug(
+                DUMMY_SP,
+                &format!("errors selecting obligation during MIR typeck: {:?}", e)
+            );
+        }
+
+        infcx.process_registered_region_obligations(
+            region_bound_pairs,
+            implicit_region_bound,
+            param_env,
+            dummy_body_id,
+        );
+
+        let data = infcx.take_and_reset_region_constraints();
+        if data.is_empty() {
+            Ok((value, None))
+        } else {
+            Ok((value, Some(Rc::new(data))))
+        }
+    }
 }
 
+
+
 pub(super) struct CustomTypeOp<F, G> {
     closure: F,
     description: G,