about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-06 09:47:28 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-06-26 10:31:49 -0400
commit214d7650c91e777c445a8ef0733c8553e34b2658 (patch)
tree3e838837fd9de8d141be3816ce7dfe9b897f9fa0 /src
parent7c62461c39d5cf8899d419be77a0ec48dd9f14bc (diff)
downloadrust-214d7650c91e777c445a8ef0733c8553e34b2658.tar.gz
rust-214d7650c91e777c445a8ef0733c8553e34b2658.zip
introduce `prove_predicates` type op
Diffstat (limited to 'src')
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs34
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/type_op.rs62
2 files changed, 65 insertions, 31 deletions
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 7a405f0a709..5e9b3ad5054 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -28,7 +28,7 @@ use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor};
 use rustc::mir::*;
 use rustc::traits::query::NoSolution;
-use rustc::traits::{self, ObligationCause, Normalized, TraitEngine};
+use rustc::traits::{ObligationCause, Normalized, TraitEngine};
 use rustc::ty::error::TypeError;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
@@ -833,7 +833,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         self.fully_perform_op(
             locations,
             || format!("eq_types({:?} = {:?})", a, b),
-            type_op::Eq::new(b, a)
+            type_op::Eq::new(b, a),
         )
     }
 
@@ -1590,27 +1590,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         );
     }
 
-    fn prove_predicates<T>(&mut self, predicates: T, location: Location)
-    where
-        T: IntoIterator<Item = ty::Predicate<'tcx>> + Clone,
-    {
-        let cause = ObligationCause::dummy();
-        let obligations: Vec<_> = predicates
-            .into_iter()
-            .map(|p| traits::Obligation::new(cause.clone(), self.param_env, p))
-            .collect();
-
-        // Micro-optimization
-        if obligations.is_empty() {
-            return;
-        }
-
+    fn prove_predicates(
+        &mut self,
+        predicates: impl IntoIterator<Item = ty::Predicate<'tcx>> + Clone,
+        location: Location,
+    ) {
         // This intermediate vector is mildly unfortunate, in that we
         // sometimes create it even when logging is disabled, but only
         // if debug-info is enabled, and I doubt it is actually
         // expensive. -nmatsakis
         let predicates_vec: Vec<_> = if cfg!(debug_assertions) {
-            obligations.iter().map(|o| o.predicate).collect()
+            predicates.clone().into_iter().collect()
         } else {
             Vec::new()
         };
@@ -1620,15 +1610,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             predicates_vec, location,
         );
 
+        let param_env = self.param_env;
         self.fully_perform_op(
             location.at_self(),
             || format!("prove_predicates({:?})", predicates_vec),
-            CustomTypeOp::new(|_this| {
-                Ok(InferOk {
-                    value: (),
-                    obligations,
-                })
-            }),
+            type_op::ProvePredicates::new(param_env, predicates),
         ).unwrap()
     }
 
diff --git a/src/librustc_mir/borrow_check/nll/type_check/type_op.rs b/src/librustc_mir/borrow_check/nll/type_check/type_op.rs
index 97453231273..0b35f3501fc 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/type_op.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/type_op.rs
@@ -9,9 +9,9 @@
 // except according to those terms.
 
 use borrow_check::nll::type_check::TypeChecker;
-use rustc::infer::InferResult;
-use rustc::traits::ObligationCause;
-use rustc::ty::Ty;
+use rustc::infer::{InferOk, InferResult};
+use rustc::traits::{Obligation, ObligationCause, PredicateObligation};
+use rustc::ty::{ParamEnv, Predicate, Ty};
 
 pub(super) trait TypeOp<'gcx, 'tcx> {
     type Output;
@@ -75,8 +75,12 @@ impl<'gcx, 'tcx> TypeOp<'gcx, 'tcx> for Subtype<'tcx> {
         }
     }
 
-    fn perform(self, type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> {
-        type_checker.infcx
+    fn perform(
+        self,
+        type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>,
+    ) -> InferResult<'tcx, Self::Output> {
+        type_checker
+            .infcx
             .at(&ObligationCause::dummy(), type_checker.param_env)
             .sup(self.sup, self.sub)
     }
@@ -104,9 +108,53 @@ impl<'gcx, 'tcx> TypeOp<'gcx, 'tcx> for Eq<'tcx> {
         }
     }
 
-    fn perform(self, type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> {
-        type_checker.infcx
+    fn perform(
+        self,
+        type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>,
+    ) -> InferResult<'tcx, Self::Output> {
+        type_checker
+            .infcx
             .at(&ObligationCause::dummy(), type_checker.param_env)
             .eq(self.a, self.b)
     }
 }
+
+pub(super) struct ProvePredicates<'tcx> {
+    obligations: Vec<PredicateObligation<'tcx>>,
+}
+
+impl<'tcx> ProvePredicates<'tcx> {
+    pub(super) fn new(
+        param_env: ParamEnv<'tcx>,
+        predicates: impl IntoIterator<Item = Predicate<'tcx>>,
+    ) -> Self {
+        ProvePredicates {
+            obligations: predicates
+                .into_iter()
+                .map(|p| Obligation::new(ObligationCause::dummy(), param_env, p))
+                .collect(),
+        }
+    }
+}
+
+impl<'gcx, 'tcx> TypeOp<'gcx, 'tcx> for ProvePredicates<'tcx> {
+    type Output = ();
+
+    fn trivial_noop(&self) -> Option<Self::Output> {
+        if self.obligations.is_empty() {
+            Some(())
+        } else {
+            None
+        }
+    }
+
+    fn perform(
+        self,
+        _type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>,
+    ) -> InferResult<'tcx, Self::Output> {
+        Ok(InferOk {
+            value: (),
+            obligations: self.obligations,
+        })
+    }
+}