introduce prove_predicates type op

This commit is contained in:
Niko Matsakis 2018-06-06 09:47:28 -04:00
parent 7c62461c39
commit 214d7650c9
2 changed files with 65 additions and 31 deletions

View File

@ -28,7 +28,7 @@ use rustc::mir::tcx::PlaceTy;
use rustc::mir::visit::{PlaceContext, Visitor};
use rustc::mir::*;
use rustc::traits::query::NoSolution;
use rustc::traits::{self, ObligationCause, Normalized, TraitEngine};
use rustc::traits::{ObligationCause, Normalized, TraitEngine};
use rustc::ty::error::TypeError;
use rustc::ty::fold::TypeFoldable;
use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeVariants};
@ -833,7 +833,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
self.fully_perform_op(
locations,
|| format!("eq_types({:?} = {:?})", a, b),
type_op::Eq::new(b, a)
type_op::Eq::new(b, a),
)
}
@ -1590,27 +1590,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
);
}
fn prove_predicates<T>(&mut self, predicates: T, location: Location)
where
T: IntoIterator<Item = ty::Predicate<'tcx>> + Clone,
{
let cause = ObligationCause::dummy();
let obligations: Vec<_> = predicates
.into_iter()
.map(|p| traits::Obligation::new(cause.clone(), self.param_env, p))
.collect();
// Micro-optimization
if obligations.is_empty() {
return;
}
fn prove_predicates(
&mut self,
predicates: impl IntoIterator<Item = ty::Predicate<'tcx>> + Clone,
location: Location,
) {
// This intermediate vector is mildly unfortunate, in that we
// sometimes create it even when logging is disabled, but only
// if debug-info is enabled, and I doubt it is actually
// expensive. -nmatsakis
let predicates_vec: Vec<_> = if cfg!(debug_assertions) {
obligations.iter().map(|o| o.predicate).collect()
predicates.clone().into_iter().collect()
} else {
Vec::new()
};
@ -1620,15 +1610,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
predicates_vec, location,
);
let param_env = self.param_env;
self.fully_perform_op(
location.at_self(),
|| format!("prove_predicates({:?})", predicates_vec),
CustomTypeOp::new(|_this| {
Ok(InferOk {
value: (),
obligations,
})
}),
type_op::ProvePredicates::new(param_env, predicates),
).unwrap()
}

View File

@ -9,9 +9,9 @@
// except according to those terms.
use borrow_check::nll::type_check::TypeChecker;
use rustc::infer::InferResult;
use rustc::traits::ObligationCause;
use rustc::ty::Ty;
use rustc::infer::{InferOk, InferResult};
use rustc::traits::{Obligation, ObligationCause, PredicateObligation};
use rustc::ty::{ParamEnv, Predicate, Ty};
pub(super) trait TypeOp<'gcx, 'tcx> {
type Output;
@ -75,8 +75,12 @@ impl<'gcx, 'tcx> TypeOp<'gcx, 'tcx> for Subtype<'tcx> {
}
}
fn perform(self, type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> {
type_checker.infcx
fn perform(
self,
type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>,
) -> InferResult<'tcx, Self::Output> {
type_checker
.infcx
.at(&ObligationCause::dummy(), type_checker.param_env)
.sup(self.sup, self.sub)
}
@ -104,9 +108,53 @@ impl<'gcx, 'tcx> TypeOp<'gcx, 'tcx> for Eq<'tcx> {
}
}
fn perform(self, type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>) -> InferResult<'tcx, Self::Output> {
type_checker.infcx
fn perform(
self,
type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>,
) -> InferResult<'tcx, Self::Output> {
type_checker
.infcx
.at(&ObligationCause::dummy(), type_checker.param_env)
.eq(self.a, self.b)
}
}
pub(super) struct ProvePredicates<'tcx> {
obligations: Vec<PredicateObligation<'tcx>>,
}
impl<'tcx> ProvePredicates<'tcx> {
pub(super) fn new(
param_env: ParamEnv<'tcx>,
predicates: impl IntoIterator<Item = Predicate<'tcx>>,
) -> Self {
ProvePredicates {
obligations: predicates
.into_iter()
.map(|p| Obligation::new(ObligationCause::dummy(), param_env, p))
.collect(),
}
}
}
impl<'gcx, 'tcx> TypeOp<'gcx, 'tcx> for ProvePredicates<'tcx> {
type Output = ();
fn trivial_noop(&self) -> Option<Self::Output> {
if self.obligations.is_empty() {
Some(())
} else {
None
}
}
fn perform(
self,
_type_checker: &mut TypeChecker<'_, 'gcx, 'tcx>,
) -> InferResult<'tcx, Self::Output> {
Ok(InferOk {
value: (),
obligations: self.obligations,
})
}
}