]> git.lizzy.rs Git - rust.git/commitdiff
modify MIR type-checker to process obligations as they are incurred
authorNiko Matsakis <niko@alum.mit.edu>
Sun, 5 Nov 2017 00:21:28 +0000 (20:21 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Wed, 15 Nov 2017 21:50:32 +0000 (16:50 -0500)
src/librustc_mir/transform/type_check.rs

index 2adb36434d8a9cc05ca4a2d2b0688e62691be82c..f45dd4f3c71eae0413ab467571fc2a860cbd9d56 100644 (file)
@@ -11,8 +11,9 @@
 //! This pass type-checks the MIR to ensure it is not broken.
 #![allow(unreachable_code)]
 
-use rustc::infer::{self, InferCtxt, InferOk};
-use rustc::traits;
+use rustc::infer::{InferCtxt, InferOk, InferResult, UnitResult};
+use rustc::traits::{self, FulfillmentContext};
+use rustc::ty::error::TypeError;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::{self, Ty, TyCtxt, TypeVariants};
 use rustc::middle::const_val::ConstVal;
@@ -366,7 +367,6 @@ fn field_ty(
 pub struct TypeChecker<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     param_env: ty::ParamEnv<'gcx>,
-    fulfillment_cx: traits::FulfillmentContext<'tcx>,
     last_span: Span,
     body_id: ast::NodeId,
     reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
@@ -380,7 +380,6 @@ fn new(
     ) -> Self {
         TypeChecker {
             infcx,
-            fulfillment_cx: traits::FulfillmentContext::new(),
             last_span: DUMMY_SP,
             body_id,
             param_env,
@@ -392,37 +391,45 @@ fn misc(&self, span: Span) -> traits::ObligationCause<'tcx> {
         traits::ObligationCause::misc(span, self.body_id)
     }
 
-    pub fn register_infer_ok_obligations<T>(&mut self, infer_ok: InferOk<'tcx, T>) -> T {
-        for obligation in infer_ok.obligations {
-            self.fulfillment_cx
-                .register_predicate_obligation(self.infcx, obligation);
-        }
-        infer_ok.value
+    fn fully_perform_op<OP, R>(&self,
+                               op: OP)
+                               -> Result<R, TypeError<'tcx>>
+        where OP: FnOnce() -> InferResult<'tcx, R>
+    {
+        let mut fulfill_cx = FulfillmentContext::new();
+        let InferOk { value, obligations } = self.infcx.commit_if_ok(|_| op())?;
+        fulfill_cx.register_predicate_obligations(self.infcx, obligations);
+        if let Err(e) = fulfill_cx.select_all_or_error(self.infcx) {
+            span_mirbug!(self, "", "errors selecting obligation: {:?}", e);
+        } // FIXME propagate
+        Ok(value)
     }
 
     fn sub_types(
-        &mut self,
+        &self,
         sub: Ty<'tcx>,
         sup: Ty<'tcx>,
         _at_location: Location,
-    ) -> infer::UnitResult<'tcx> {
-        self.infcx
-            .at(&self.misc(self.last_span), self.param_env)
-            .sup(sup, sub)
-            .map(|ok| self.register_infer_ok_obligations(ok))
+    ) -> UnitResult<'tcx> {
+        self.fully_perform_op(|| {
+            self.infcx
+                .at(&self.misc(self.last_span), self.param_env)
+                .sup(sup, sub)
+        })
     }
 
     fn eq_types(
-        &mut self,
-        span: Span,
+        &self,
+        _span: Span,
         a: Ty<'tcx>,
         b: Ty<'tcx>,
         _at_location: Location,
-    ) -> infer::UnitResult<'tcx> {
-        self.infcx
-            .at(&self.misc(span), self.param_env)
-            .eq(b, a)
-            .map(|ok| self.register_infer_ok_obligations(ok))
+    ) -> UnitResult<'tcx> {
+        self.fully_perform_op(|| {
+            self.infcx
+                .at(&self.misc(self.last_span), self.param_env)
+                .eq(b, a)
+        })
     }
 
     fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
@@ -898,26 +905,13 @@ fn normalize<T>(&mut self, value: &T, _location: Location) -> T
     where
         T: fmt::Debug + TypeFoldable<'tcx>,
     {
-        let mut selcx = traits::SelectionContext::new(self.infcx);
-        let cause = traits::ObligationCause::misc(self.last_span, ast::CRATE_NODE_ID);
-        let traits::Normalized { value, obligations } =
-            traits::normalize(&mut selcx, self.param_env, cause, value);
-
-        debug!("normalize: value={:?} obligations={:?}", value, obligations);
-
-        let fulfill_cx = &mut self.fulfillment_cx;
-        for obligation in obligations {
-            fulfill_cx.register_predicate_obligation(self.infcx, obligation);
-        }
-
-        value
-    }
-
-    fn verify_obligations(&mut self, mir: &Mir<'tcx>) {
-        self.last_span = mir.span;
-        if let Err(e) = self.fulfillment_cx.select_all_or_error(self.infcx) {
-            span_mirbug!(self, "", "errors selecting obligation: {:?}", e);
-        }
+        self.fully_perform_op(|| {
+            let mut selcx = traits::SelectionContext::new(self.infcx);
+            let cause = traits::ObligationCause::misc(self.last_span, ast::CRATE_NODE_ID);
+            let traits::Normalized { value, obligations } =
+                traits::normalize(&mut selcx, self.param_env, cause, value);
+            Ok(InferOk { value, obligations })
+        }).unwrap()
     }
 }
 
@@ -946,7 +940,6 @@ fn run_pass<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, src: MirSource, mir: &
                 }
             }
             checker.typeck_mir(mir);
-            checker.verify_obligations(mir);
         });
     }
 }