Return an instantiated environment instead of a generic one

This commit is contained in:
scalexm 2018-11-23 21:03:27 +01:00
parent 8cadd59674
commit ec7362442c
4 changed files with 29 additions and 29 deletions

View File

@ -684,7 +684,7 @@ define_queries! { <'tcx>
) -> Clauses<'tcx>,
// Get the chalk-style environment of the given item.
[] fn environment: Environment(DefId) -> ty::Binder<traits::Environment<'tcx>>,
[] fn environment: Environment(DefId) -> traits::Environment<'tcx>,
},
Linking {

View File

@ -256,6 +256,8 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
) -> Vec<Clause<'tcx>> {
use rustc::traits::WhereClause::*;
debug!("program_clauses(goal = {:?})", goal);
let mut clauses = match goal {
DomainGoal::Holds(Implemented(trait_predicate)) => {
// These come from:
@ -345,20 +347,21 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
self.infcx.tcx.program_clauses_for(data.item_def_id)
}
// These types are always WF and non-parametric.
// These types are always WF.
ty::Bool |
ty::Char |
ty::Int(..) |
ty::Uint(..) |
ty::Float(..) |
ty::Str |
ty::Param(..) |
ty::Never => {
let wf_clause = ProgramClause {
goal: DomainGoal::WellFormed(WellFormed::Ty(ty)),
hypotheses: ty::List::empty(),
category: ProgramClauseCategory::WellFormed,
};
let wf_clause = Clause::ForAll(ty::Binder::dummy(wf_clause));
let wf_clause = Clause::Implies(wf_clause);
self.infcx.tcx.mk_clauses(iter::once(wf_clause))
}
@ -415,7 +418,6 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
ty::UnnormalizedProjection(..) |
ty::Infer(..) |
ty::Bound(..) |
ty::Param(..) |
ty::Error => {
bug!("unexpected type {:?}", ty)
}
@ -458,13 +460,18 @@ impl ChalkInferenceContext<'cx, 'gcx, 'tcx> {
}
};
debug!("program_clauses: clauses = {:?}", clauses);
debug!("program_clauses: adding clauses from environment = {:?}", environment);
let environment = self.infcx.tcx.lift_to_global(environment)
.expect("environment is not global");
clauses.extend(
self.infcx.tcx.program_clauses_for_env(environment)
.into_iter()
.cloned()
);
let env_clauses = self.infcx.tcx.program_clauses_for_env(environment);
debug!("program_clauses: env_clauses = {:?}", env_clauses);
clauses.extend(env_clauses.into_iter().cloned());
clauses.extend(environment.clauses.iter().cloned());
clauses
}
}

View File

@ -105,11 +105,11 @@ impl ClauseVisitor<'set, 'a, 'tcx> {
ty::Never |
ty::Infer(..) |
ty::Placeholder(..) |
ty::Param(..) |
ty::Bound(..) => (),
ty::GeneratorWitness(..) |
ty::UnnormalizedProjection(..) |
ty::Param(..) |
ty::Error => {
bug!("unexpected type {:?}", ty);
}
@ -192,25 +192,23 @@ crate fn program_clauses_for_env<'a, 'tcx>(
crate fn environment<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId
) -> ty::Binder<Environment<'tcx>> {
) -> Environment<'tcx> {
use super::{Lower, IntoFromEnvGoal};
use rustc::hir::{Node, TraitItemKind, ImplItemKind, ItemKind, ForeignItemKind};
use rustc::ty::subst::{Subst, Substs};
debug!("environment(def_id = {:?})", def_id);
// The environment of an impl Trait type is its defining function's environment.
if let Some(parent) = ty::is_impl_trait_defn(tcx, def_id) {
return environment(tcx, parent);
}
let bound_vars = Substs::bound_vars_for_item(tcx, def_id);
// Compute the bounds on `Self` and the type parameters.
let ty::InstantiatedPredicates { predicates } = tcx.predicates_of(def_id)
.instantiate_identity(tcx);
let clauses = predicates.into_iter()
.map(|predicate| predicate.lower())
.map(|predicate| predicate.subst(tcx, bound_vars))
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_from_env_goal()))
.map(|domain_goal| domain_goal.map_bound(|bound| bound.into_program_clause()))
@ -255,20 +253,18 @@ crate fn environment<'a, 'tcx>(
// are well-formed.
if is_impl {
let trait_ref = tcx.impl_trait_ref(def_id)
.expect("not an impl")
.subst(tcx, bound_vars);
.expect("not an impl");
input_tys.extend(
trait_ref.substs.types().flat_map(|ty| ty.walk())
trait_ref.input_types().flat_map(|ty| ty.walk())
);
}
// In an fn, we assume that the arguments and all their constituents are
// well-formed.
if is_fn {
// `skip_binder` because we move region parameters to the root binder,
// restored in the return type of this query
let fn_sig = tcx.fn_sig(def_id).skip_binder().subst(tcx, bound_vars);
let fn_sig = tcx.fn_sig(def_id);
let fn_sig = tcx.liberate_late_bound_regions(def_id, &fn_sig);
input_tys.extend(
fn_sig.inputs().iter().flat_map(|ty| ty.walk())
@ -277,17 +273,14 @@ crate fn environment<'a, 'tcx>(
let clauses = clauses.chain(
input_tys.into_iter()
// Filter out type parameters
.filter(|ty| match ty.sty {
ty::Bound(..) => false,
_ => true,
})
.map(|ty| DomainGoal::FromEnv(FromEnv::Ty(ty)))
.map(|domain_goal| domain_goal.into_program_clause())
.map(Clause::Implies)
);
ty::Binder::bind(Environment {
debug!("environment: clauses = {:?}", clauses);
Environment {
clauses: tcx.mk_clauses(clauses),
})
}
}

View File

@ -626,7 +626,7 @@ impl<'a, 'tcx> ClauseDumper<'a, 'tcx> {
if attr.check_name("rustc_dump_env_program_clauses") {
let environment = self.tcx.environment(def_id);
clauses = Some(self.tcx.program_clauses_for_env(*environment.skip_binder()));
clauses = Some(self.tcx.program_clauses_for_env(environment));
}
if let Some(clauses) = clauses {