create a QueryRegionConstraint type
Chalk wants to be able to pass these constraints around. Also, the form we were using in our existing queries was not as general as we are going to need.
This commit is contained in:
parent
3aa1085cfc
commit
c8a52850cf
3 changed files with 44 additions and 69 deletions
|
|
@ -1352,10 +1352,6 @@ impl_stable_hash_for!(
|
|||
}
|
||||
);
|
||||
|
||||
impl_stable_hash_for!(struct infer::canonical::QueryRegionConstraints<'tcx> {
|
||||
region_outlives, ty_outlives
|
||||
});
|
||||
|
||||
impl_stable_hash_for!(enum infer::canonical::Certainty {
|
||||
Proven, Ambiguous
|
||||
});
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ use traits::{Obligation, ObligationCause, PredicateObligation};
|
|||
use ty::{self, CanonicalVar, Lift, Region, Slice, Ty, TyCtxt, TypeFlags};
|
||||
use ty::subst::{Kind, UnpackedKind};
|
||||
use ty::fold::{TypeFoldable, TypeFolder};
|
||||
use util::captures::Captures;
|
||||
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
|
|
@ -121,7 +120,7 @@ pub enum CanonicalTyVarKind {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct QueryResult<'tcx, R> {
|
||||
pub var_values: CanonicalVarValues<'tcx>,
|
||||
pub region_constraints: QueryRegionConstraints<'tcx>,
|
||||
pub region_constraints: Vec<QueryRegionConstraint<'tcx>>,
|
||||
pub certainty: Certainty,
|
||||
pub value: R,
|
||||
}
|
||||
|
|
@ -181,12 +180,7 @@ impl<'tcx, R> Canonical<'tcx, QueryResult<'tcx, R>> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Subset of `RegionConstraintData` produced by trait query.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct QueryRegionConstraints<'tcx> {
|
||||
pub region_outlives: Vec<(Region<'tcx>, Region<'tcx>)>,
|
||||
pub ty_outlives: Vec<(Ty<'tcx>, Region<'tcx>)>,
|
||||
}
|
||||
pub type QueryRegionConstraint<'tcx> = ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
|
||||
|
||||
/// Trait implemented by values that can be canonicalized. It mainly
|
||||
/// serves to identify the interning table we will use.
|
||||
|
|
@ -382,35 +376,29 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
|
|||
&'a self,
|
||||
cause: &'a ObligationCause<'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
unsubstituted_region_constraints: &'a QueryRegionConstraints<'tcx>,
|
||||
unsubstituted_region_constraints: &'a [QueryRegionConstraint<'tcx>],
|
||||
result_subst: &'a CanonicalVarValues<'tcx>,
|
||||
) -> impl Iterator<Item = PredicateObligation<'tcx>> + Captures<'gcx> + 'a {
|
||||
let QueryRegionConstraints {
|
||||
region_outlives,
|
||||
ty_outlives,
|
||||
} = unsubstituted_region_constraints;
|
||||
|
||||
let region_obligations = region_outlives.iter().map(move |(r1, r2)| {
|
||||
let r1 = substitute_value(self.tcx, result_subst, r1);
|
||||
) -> impl Iterator<Item = PredicateObligation<'tcx>> + 'a {
|
||||
Box::new(unsubstituted_region_constraints.iter().map(move |constraint| {
|
||||
let ty::OutlivesPredicate(k1, r2) = constraint.skip_binder(); // restored below
|
||||
let k1 = substitute_value(self.tcx, result_subst, k1);
|
||||
let r2 = substitute_value(self.tcx, result_subst, r2);
|
||||
Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))),
|
||||
)
|
||||
});
|
||||
match k1.unpack() {
|
||||
UnpackedKind::Lifetime(r1) =>
|
||||
Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::RegionOutlives(ty::Binder(ty::OutlivesPredicate(r1, r2))),
|
||||
),
|
||||
|
||||
let ty_obligations = ty_outlives.iter().map(move |(t1, r2)| {
|
||||
let t1 = substitute_value(self.tcx, result_subst, t1);
|
||||
let r2 = substitute_value(self.tcx, result_subst, r2);
|
||||
Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))),
|
||||
)
|
||||
});
|
||||
|
||||
region_obligations.chain(ty_obligations)
|
||||
UnpackedKind::Type(t1) =>
|
||||
Obligation::new(
|
||||
cause.clone(),
|
||||
param_env,
|
||||
ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t1, r2))),
|
||||
),
|
||||
}
|
||||
})) as Box<dyn Iterator<Item = _>>
|
||||
}
|
||||
|
||||
/// Given two sets of values for the same set of canonical variables, unify them.
|
||||
|
|
@ -913,19 +901,6 @@ BraceStructTypeFoldableImpl! {
|
|||
}
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx> TypeFoldable<'tcx> for QueryRegionConstraints<'tcx> {
|
||||
region_outlives, ty_outlives
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructLiftImpl! {
|
||||
impl<'a, 'tcx> Lift<'tcx> for QueryRegionConstraints<'a> {
|
||||
type Lifted = QueryRegionConstraints<'tcx>;
|
||||
region_outlives, ty_outlives
|
||||
}
|
||||
}
|
||||
|
||||
BraceStructTypeFoldableImpl! {
|
||||
impl<'tcx, R> TypeFoldable<'tcx> for QueryResult<'tcx, R> {
|
||||
var_values, region_constraints, certainty, value
|
||||
|
|
|
|||
|
|
@ -9,8 +9,7 @@
|
|||
// except according to those terms.
|
||||
|
||||
use rustc::infer::InferCtxt;
|
||||
use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryRegionConstraints,
|
||||
QueryResult};
|
||||
use rustc::infer::canonical::{CanonicalVarValues, Canonicalize, Certainty, QueryResult};
|
||||
use rustc::infer::region_constraints::{Constraint, RegionConstraintData};
|
||||
use rustc::traits::{FulfillmentContext, TraitEngine};
|
||||
use rustc::traits::query::NoSolution;
|
||||
|
|
@ -62,7 +61,7 @@ where
|
|||
|
||||
let region_obligations = infcx.take_registered_region_obligations();
|
||||
|
||||
let (region_outlives, ty_outlives) = infcx.with_region_constraints(|region_constraints| {
|
||||
let region_constraints = infcx.with_region_constraints(|region_constraints| {
|
||||
let RegionConstraintData {
|
||||
constraints,
|
||||
verifys,
|
||||
|
|
@ -72,24 +71,32 @@ where
|
|||
assert!(verifys.is_empty());
|
||||
assert!(givens.is_empty());
|
||||
|
||||
let region_outlives: Vec<_> = constraints
|
||||
let mut outlives: Vec<_> = constraints
|
||||
.into_iter()
|
||||
.map(|(k, _)| match *k {
|
||||
Constraint::VarSubVar(v1, v2) => {
|
||||
(tcx.mk_region(ty::ReVar(v1)), tcx.mk_region(ty::ReVar(v2)))
|
||||
Constraint::VarSubVar(v1, v2) => ty::OutlivesPredicate(
|
||||
tcx.mk_region(ty::ReVar(v1)).into(),
|
||||
tcx.mk_region(ty::ReVar(v2)),
|
||||
),
|
||||
Constraint::VarSubReg(v1, r2) => {
|
||||
ty::OutlivesPredicate(tcx.mk_region(ty::ReVar(v1)).into(), r2)
|
||||
}
|
||||
Constraint::VarSubReg(v1, r2) => (tcx.mk_region(ty::ReVar(v1)), r2),
|
||||
Constraint::RegSubVar(r1, v2) => (r1, tcx.mk_region(ty::ReVar(v2))),
|
||||
Constraint::RegSubReg(r1, r2) => (r1, r2),
|
||||
Constraint::RegSubVar(r1, v2) => {
|
||||
ty::OutlivesPredicate(r1.into(), tcx.mk_region(ty::ReVar(v2)))
|
||||
}
|
||||
Constraint::RegSubReg(r1, r2) => ty::OutlivesPredicate(r1.into(), r2),
|
||||
})
|
||||
.map(ty::Binder) // no bound regions in the code above
|
||||
.collect();
|
||||
|
||||
let ty_outlives: Vec<_> = region_obligations
|
||||
.into_iter()
|
||||
.map(|(_, r_o)| (r_o.sup_type, r_o.sub_region))
|
||||
.collect();
|
||||
outlives.extend(
|
||||
region_obligations
|
||||
.into_iter()
|
||||
.map(|(_, r_o)| ty::OutlivesPredicate(r_o.sup_type.into(), r_o.sub_region))
|
||||
.map(ty::Binder) // no bound regions in the code above
|
||||
);
|
||||
|
||||
(region_outlives, ty_outlives)
|
||||
outlives
|
||||
});
|
||||
|
||||
let certainty = if ambig_errors.is_empty() {
|
||||
|
|
@ -100,10 +107,7 @@ where
|
|||
|
||||
let (canonical_result, _) = infcx.canonicalize_response(&QueryResult {
|
||||
var_values: inference_vars,
|
||||
region_constraints: QueryRegionConstraints {
|
||||
region_outlives,
|
||||
ty_outlives,
|
||||
},
|
||||
region_constraints,
|
||||
certainty,
|
||||
value: answer,
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue