mk fully_perform_op_and_get_region_constraint_data
a TypeOp method
This commit is contained in:
parent
efc84c83f9
commit
6ac89174b8
@ -9,7 +9,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use borrow_check::nll::region_infer::Cause;
|
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 borrow_check::nll::type_check::AtLocation;
|
||||||
use dataflow::move_paths::{HasMoveData, MoveData};
|
use dataflow::move_paths::{HasMoveData, MoveData};
|
||||||
use dataflow::MaybeInitializedPlaces;
|
use dataflow::MaybeInitializedPlaces;
|
||||||
@ -218,10 +218,15 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo
|
|||||||
|
|
||||||
let param_env = cx.param_env;
|
let param_env = cx.param_env;
|
||||||
let (dropped_kinds, region_constraint_data) =
|
let (dropped_kinds, region_constraint_data) =
|
||||||
cx.fully_perform_op_and_get_region_constraint_data(DropckOutlives::new(
|
DropckOutlives::new(
|
||||||
param_env,
|
param_env,
|
||||||
dropped_ty,
|
dropped_ty,
|
||||||
)).unwrap();
|
).fully_perform(
|
||||||
|
cx.infcx,
|
||||||
|
cx.region_bound_pairs,
|
||||||
|
cx.implicit_region_bound,
|
||||||
|
cx.param_env,
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
DropData {
|
DropData {
|
||||||
dropped_kinds,
|
dropped_kinds,
|
||||||
|
@ -21,12 +21,12 @@ use dataflow::FlowAtLocation;
|
|||||||
use dataflow::MaybeInitializedPlaces;
|
use dataflow::MaybeInitializedPlaces;
|
||||||
use rustc::hir::def_id::DefId;
|
use rustc::hir::def_id::DefId;
|
||||||
use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
|
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::interpret::EvalErrorKind::BoundsCheck;
|
||||||
use rustc::mir::tcx::PlaceTy;
|
use rustc::mir::tcx::PlaceTy;
|
||||||
use rustc::mir::visit::{PlaceContext, Visitor};
|
use rustc::mir::visit::{PlaceContext, Visitor};
|
||||||
use rustc::mir::*;
|
use rustc::mir::*;
|
||||||
use rustc::traits::{ObligationCause, TraitEngine};
|
use rustc::traits::ObligationCause;
|
||||||
use rustc::ty::error::TypeError;
|
use rustc::ty::error::TypeError;
|
||||||
use rustc::ty::fold::TypeFoldable;
|
use rustc::ty::fold::TypeFoldable;
|
||||||
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
|
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
|
||||||
@ -733,18 +733,18 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
|||||||
locations: Locations,
|
locations: Locations,
|
||||||
op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
|
op: impl type_op::TypeOp<'gcx, 'tcx, Output = R>,
|
||||||
) -> Result<R, TypeError<'tcx>> {
|
) -> Result<R, TypeError<'tcx>> {
|
||||||
match op.trivial_noop() {
|
let (r, opt_data) = op.fully_perform(
|
||||||
Ok(r) => Ok(r),
|
self.infcx,
|
||||||
Err(op) => {
|
self.region_bound_pairs,
|
||||||
let (r, opt_data) = self.fully_perform_op_and_get_region_constraint_data(op)?;
|
self.implicit_region_bound,
|
||||||
|
self.param_env,
|
||||||
|
)?;
|
||||||
|
|
||||||
if let Some(data) = opt_data {
|
if let Some(data) = opt_data {
|
||||||
self.push_region_constraints(locations, data);
|
self.push_region_constraints(locations, data);
|
||||||
}
|
|
||||||
|
|
||||||
Ok(r)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push_region_constraints(
|
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(
|
fn sub_types(
|
||||||
&mut self,
|
&mut self,
|
||||||
sub: Ty<'tcx>,
|
sub: Ty<'tcx>,
|
||||||
|
@ -9,12 +9,16 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use rustc::infer::{InferCtxt, InferOk, InferResult};
|
use rustc::infer::{InferCtxt, InferOk, InferResult};
|
||||||
|
use rustc::infer::region_constraints::{GenericKind, RegionConstraintData};
|
||||||
use rustc::traits::query::NoSolution;
|
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::fold::TypeFoldable;
|
||||||
use rustc::ty::subst::Kind;
|
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 std::fmt;
|
||||||
|
use syntax::codemap::DUMMY_SP;
|
||||||
|
|
||||||
pub(super) trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
|
pub(super) trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
|
||||||
type Output;
|
type Output;
|
||||||
@ -23,9 +27,65 @@ pub(super) trait TypeOp<'gcx, 'tcx>: Sized + fmt::Debug {
|
|||||||
/// produce the output, else returns `Err(self)` back.
|
/// produce the output, else returns `Err(self)` back.
|
||||||
fn trivial_noop(self) -> Result<Self::Output, Self>;
|
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>;
|
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> {
|
pub(super) struct CustomTypeOp<F, G> {
|
||||||
closure: F,
|
closure: F,
|
||||||
description: G,
|
description: G,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user