From efa09dbea5bd886389f994d511e502422b8d5149 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 4 Nov 2017 20:21:28 -0400 Subject: [PATCH] modify MIR type-checker to process obligations as they are incurred --- src/librustc_mir/transform/type_check.rs | 81 +++++++++++------------- 1 file changed, 37 insertions(+), 44 deletions(-) diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs index 2adb36434d8..f45dd4f3c71 100644 --- a/src/librustc_mir/transform/type_check.rs +++ b/src/librustc_mir/transform/type_check.rs @@ -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(&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(&self, + op: OP) + -> Result> + 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(&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); }); } }