use rustc::hir::def_id::DefId;
use rustc::hir::intravisit::{self, NestedVisitorMap, Visitor};
+use rustc::hir::map::definitions::DefPathData;
+use rustc::hir::{self, ImplPolarity};
use rustc::traits::{Clause, DomainGoal, Goal, PolyDomainGoal, ProgramClause, WhereClauseAtom};
use rustc::ty::subst::Substs;
use rustc::ty::{self, Slice, TyCtxt};
+use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
-use syntax::ast;
+use std::mem;
use syntax::ast;
use std::iter;
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
) -> Lrc<&'tcx Slice<Clause<'tcx>>> {
- let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
- let node = tcx.hir.find(node_id).unwrap();
- match node {
- hir::map::Node::NodeItem(item) => match item.node {
- hir::ItemTrait(..) => program_clauses_for_trait(tcx, def_id),
- hir::ItemImpl(..) => program_clauses_for_impl(tcx, def_id),
- _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
- },
- hir::map::Node::NodeImplItem(item) => {
- if let hir::ImplItemKind::Type(..) = item.node {
- program_clauses_for_associated_type_value(tcx, def_id)
- } else {
- Lrc::new(tcx.mk_clauses(iter::empty::<Clause>()))
- }
- }
+ match tcx.def_key(def_id).disambiguated_data.data {
+ DefPathData::Trait(_) => program_clauses_for_trait(tcx, def_id),
+ DefPathData::Impl => program_clauses_for_impl(tcx, def_id),
+ DefPathData::AssocTypeInImpl(..) => program_clauses_for_associated_type_value(tcx, def_id),
+ _ => Lrc::new(Slice::empty()),
+ }
+}
+
+crate fn program_clauses_for_env<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+) -> Lrc<&'tcx Slice<Clause<'tcx>>> {
+ debug!("program_clauses_for_env(param_env={:?})", param_env);
+
+ let mut last_round = FxHashSet();
+ last_round.extend(
+ param_env
+ .caller_bounds
+ .iter()
+ .flat_map(|&p| predicate_def_id(p)),
+ );
+
+ let mut closure = last_round.clone();
+ let mut next_round = FxHashSet();
+ while !last_round.is_empty() {
+ next_round.extend(
+ last_round
+ .drain()
+ .flat_map(|def_id| {
+ tcx.predicates_of(def_id)
+ .instantiate_identity(tcx)
+ .predicates
+ })
+ .flat_map(|p| predicate_def_id(p))
+ .filter(|&def_id| closure.insert(def_id)),
+ );
+ mem::swap(&mut next_round, &mut last_round);
+ }
+
+ debug!("program_clauses_for_env: closure = {:#?}", closure);
- // FIXME: other constructions e.g. traits, associated types...
- _ => Lrc::new(tcx.mk_clauses(iter::empty::<Clause>())),
+ return Lrc::new(
+ tcx.mk_clauses(
+ closure
+ .into_iter()
+ .flat_map(|def_id| tcx.program_clauses_for(def_id).iter().cloned()),
+ ),
+ );
+
+ /// Given that `predicate` is in the environment, returns the
+ /// def-id of something (e.g., a trait, associated item, etc)
+ /// whose predicates can also be assumed to be true. We will
+ /// compute the transitive closure of such things.
+ fn predicate_def_id<'tcx>(predicate: ty::Predicate<'tcx>) -> Option<DefId> {
+ match predicate {
+ ty::Predicate::Trait(predicate) => Some(predicate.def_id()),
+
+ ty::Predicate::Projection(projection) => Some(projection.item_def_id()),
+
+ ty::Predicate::WellFormed(..)
+ | ty::Predicate::RegionOutlives(..)
+ | ty::Predicate::TypeOutlives(..)
+ | ty::Predicate::ObjectSafe(..)
+ | ty::Predicate::ClosureKind(..)
+ | ty::Predicate::Subtype(..)
+ | ty::Predicate::ConstEvaluatable(..) => None,
+ }
}
}
--- /dev/null
+error: program clause dump
+ --> $DIR/lower_env1.rs:16:1
+ |
+LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
+ = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
+ = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
+
+error: program clause dump
+ --> $DIR/lower_env1.rs:19:1
+ |
+LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ |
+ = note: Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized).
+ = note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
+ = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
+ = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
+ = note: Implemented(Self: Foo) :- FromEnv(Self: Foo).
+
+error: aborting due to 2 previous errors
+