about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-06-06 10:33:07 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-06-26 10:31:49 -0400
commit846cc263cf4aee40064598c8a9c1d26c50daa7c2 (patch)
tree483c7293c99562646686c9aeceb4d7082a5d1398
parentf998628e5c661f07bf0db7985b2949411a23064c (diff)
downloadrust-846cc263cf4aee40064598c8a9c1d26c50daa7c2.tar.gz
rust-846cc263cf4aee40064598c8a9c1d26c50daa7c2.zip
make normalize into an op
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs32
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/type_op.rs53
2 files changed, 58 insertions, 27 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 e6211c4ed7f..99d8ed85af3 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -15,7 +15,6 @@ use borrow_check::location::LocationTable;
 use borrow_check::nll::facts::AllFacts;
 use borrow_check::nll::region_infer::Cause;
 use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, OutlivesConstraint, TypeTest};
-use borrow_check::nll::type_check::type_op::{CustomTypeOp, TypeOp};
 use borrow_check::nll::universal_regions::UniversalRegions;
 use dataflow::move_paths::MoveData;
 use dataflow::FlowAtLocation;
@@ -27,8 +26,7 @@ use rustc::mir::interpret::EvalErrorKind::BoundsCheck;
 use rustc::mir::tcx::PlaceTy;
 use rustc::mir::visit::{PlaceContext, Visitor};
 use rustc::mir::*;
-use rustc::traits::query::NoSolution;
-use rustc::traits::{ObligationCause, Normalized, TraitEngine};
+use rustc::traits::{ObligationCause, TraitEngine};
 use rustc::ty::error::TypeError;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
@@ -734,7 +732,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         locations: Locations,
         describe_op: impl Fn() -> String,
-        op: impl TypeOp<'gcx, 'tcx, Output = R>,
+        op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
     ) -> Result<R, TypeError<'tcx>> {
         match op.trivial_noop() {
             Ok(r) => Ok(r),
@@ -784,7 +782,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     fn fully_perform_op_and_get_region_constraint_data<R>(
         &mut self,
         describe_op: impl Fn() -> String,
-        op: impl TypeOp<'gcx, 'tcx, Output = R>,
+        op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
     ) -> Result<(R, Option<Rc<RegionConstraintData<'tcx>>>), TypeError<'tcx>> {
         if cfg!(debug_assertions) {
             info!(
@@ -1649,30 +1647,12 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     where
         T: fmt::Debug + TypeFoldable<'tcx>,
     {
-        // Micro-optimization: avoid work when we don't have to
-        if !value.has_projections() {
-            return value.clone();
-        }
-
         debug!("normalize(value={:?}, location={:?})", value, location);
+        let value1 = value.clone(); // FIXME move describe into type_op
         self.fully_perform_op(
             location.to_locations(),
-            || format!("normalize(value={:?})", value),
-            CustomTypeOp::new(|this| {
-                let Normalized { value, obligations } = this
-                    .infcx
-                    .at(&ObligationCause::dummy(), this.param_env)
-                    .normalize(&value)
-                    .unwrap_or_else(|NoSolution| {
-                        span_bug!(
-                            this.last_span,
-                            "normalization of `{:?}` failed at {:?}",
-                            value,
-                            location,
-                        );
-                    });
-                Ok(InferOk { value, obligations })
-            }),
+            || format!("normalize(value={:?})", value1),
+            type_op::Normalize::new(value),
         ).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 d85a83ac3fc..43c11c61eff 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
@@ -10,8 +10,11 @@
 
 use borrow_check::nll::type_check::TypeChecker;
 use rustc::infer::{InferOk, InferResult};
-use rustc::traits::{Obligation, ObligationCause, PredicateObligation};
+use rustc::traits::{Normalized, Obligation, ObligationCause, PredicateObligation};
+use rustc::traits::query::NoSolution;
 use rustc::ty::{ParamEnv, Predicate, Ty};
+use rustc::ty::fold::TypeFoldable;
+use std::fmt;
 
 pub(super) trait TypeOp<'gcx, 'tcx>: Sized {
     type Output;
@@ -160,3 +163,51 @@ impl<'gcx, 'tcx> TypeOp<'gcx, 'tcx> for ProvePredicates<'tcx> {
         })
     }
 }
+
+pub(super) struct Normalize<T> {
+    value: T
+}
+
+impl<'tcx, T> Normalize<T>
+where
+    T: fmt::Debug + TypeFoldable<'tcx>,
+{
+    pub(super) fn new(
+        value: T
+    ) -> Self {
+        Self { value }
+    }
+}
+
+impl<'gcx, 'tcx, T> TypeOp<'gcx, 'tcx> for Normalize<T>
+where
+    T: fmt::Debug + TypeFoldable<'tcx>,
+{
+    type Output = T;
+
+    fn trivial_noop(self) -> Result<Self::Output, Self> {
+        if !self.value.has_projections() {
+            Ok(self.value)
+        } else {
+            Err(self)
+        }
+    }
+
+    fn perform(
+        self,
+        type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>,
+    ) -> InferResult<'tcx, Self::Output> {
+        let Normalized { value, obligations } = type_checker
+            .infcx
+            .at(&ObligationCause::dummy(), type_checker.param_env)
+            .normalize(&self.value)
+            .unwrap_or_else(|NoSolution| {
+                span_bug!(
+                    type_checker.last_span,
+                    "normalization of `{:?}` failed",
+                    self.value,
+                );
+            });
+        Ok(InferOk { value, obligations })
+    }
+}