diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2018-06-07 06:02:08 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2018-06-26 10:31:49 -0400 |
| commit | 6ac89174b8b1f75ff867588e82a51e7134aaba31 (patch) | |
| tree | e00f96864d94d19a6e5ca388b9784e849e410ec0 | |
| parent | efc84c83f91e405830aea88ecab2a2495dd9e1db (diff) | |
| download | rust-6ac89174b8b1f75ff867588e82a51e7134aaba31.tar.gz rust-6ac89174b8b1f75ff867588e82a51e7134aaba31.zip | |
mk `fully_perform_op_and_get_region_constraint_data` a TypeOp method
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, |
