[] GenericsOfItem(DefId),
[] PredicatesOfItem(DefId),
[] ExplicitPredicatesOfItem(DefId),
+ [] PredicatesDefinedOnItem(DefId),
[] InferredOutlivesOf(DefId),
[] InferredOutlivesCrate(CrateNum),
[] SuperPredicatesOfItem(DefId),
[] fn type_of: TypeOfItem(DefId) -> Ty<'tcx>,
/// Maps from the def-id of an item (trait/struct/enum/fn) to its
- /// associated generics and predicates.
+ /// associated generics.
[] fn generics_of: GenericsOfItem(DefId) -> &'tcx ty::Generics,
+
+ /// Maps from the def-id of an item (trait/struct/enum/fn) to the
+ /// predicates (where clauses) that must be proven true in order
+ /// to reference it. This is almost always the "predicates query"
+ /// that you want.
+ ///
+ /// `predicates_of` builds on `predicates_defined_on` -- in fact,
+ /// it is almost always the same as that query, except for the
+ /// case of traits. For traits, `predicates_of` contains
+ /// an additional `Self: Trait<...>` predicate that users don't
+ /// actually write. This reflects the fact that to invoke the
+ /// trait (e.g., via `Default::default`) you must supply types
+ /// that actually implement the trait. (However, this extra
+ /// predicate gets in the way of some checks, which are intended
+ /// to operate over only the actual where-clauses written by the
+ /// user.)
[] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
+
+ /// Maps from the def-id of an item (trait/struct/enum/fn) to the
+ /// predicates (where clauses) directly defined on it. This is
+ /// equal to the `explicit_predicates_of` predicates plus the
+ /// `inferred_outlives_of` predicates.
+ [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) -> ty::GenericPredicates<'tcx>,
+
+ /// Returns the predicates written explicit by the user.
[] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>,
+ /// Returns the inferred outlives predicates (e.g., for `struct
+ /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`).
+ [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
+
/// Maps from the def-id of a trait to the list of
/// super-predicates. This is a subset of the full list of
/// predicates. We store these in a separate map because we must
/// (inferred) variance.
[] fn variances_of: ItemVariances(DefId) -> Lrc<Vec<ty::Variance>>,
- /// Maps from def-id of a type to its (inferred) outlives.
- [] fn inferred_outlives_of: InferredOutlivesOf(DefId) -> Lrc<Vec<ty::Predicate<'tcx>>>,
-
/// Maps from def-id of a type to its (inferred) outlives.
[] fn inferred_outlives_crate: InferredOutlivesCrate(CrateNum)
-> Lrc<ty::CratePredicatesMap<'tcx>>,
DepKind::TypeOfItem => { force!(type_of, def_id!()); }
DepKind::GenericsOfItem => { force!(generics_of, def_id!()); }
DepKind::PredicatesOfItem => { force!(predicates_of, def_id!()); }
+ DepKind::PredicatesDefinedOnItem => { force!(predicates_defined_on, def_id!()); }
DepKind::ExplicitPredicatesOfItem => { force!(explicit_predicates_of, def_id!()); }
DepKind::InferredOutlivesOf => { force!(inferred_outlives_of, def_id!()); }
DepKind::InferredOutlivesCrate => { force!(inferred_outlives_crate, LOCAL_CRATE); }
tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess))
}
predicates_of => { cdata.get_predicates(def_id.index, tcx) }
+ predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) }
super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) }
trait_def => {
tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess))
self.entry(item_id).predicates.unwrap().decode((self, tcx))
}
+ pub fn get_predicates_defined_on(&self,
+ item_id: DefIndex,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> ty::GenericPredicates<'tcx> {
+ self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx))
+ }
+
pub fn get_super_predicates(&self,
item_id: DefIndex,
tcx: TyCtxt<'a, 'tcx, 'tcx>)
},
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
+ predicates_defined_on: None,
mir: self.encode_optimized_mir(def_id),
}
variances: LazySeq::empty(),
generics: None,
predicates: None,
+ predicates_defined_on: None,
mir: None
}
variances: LazySeq::empty(),
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
+ predicates_defined_on: None,
mir: None,
}
},
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
+ predicates_defined_on: None,
mir: self.encode_optimized_mir(def_id),
}
self.lazy(&tcx.predicates_of(def_id))
}
+ fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy<ty::GenericPredicates<'tcx>> {
+ debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id);
+ let tcx = self.tcx;
+ self.lazy(&tcx.predicates_defined_on(def_id))
+ }
+
fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> {
debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id);
let tcx = self.tcx;
},
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
+ predicates_defined_on: None,
mir: self.encode_optimized_mir(def_id),
}
},
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
+ predicates_defined_on: None,
mir: if mir { self.encode_optimized_mir(def_id) } else { None },
}
_ => None,
},
+ // The only time that `predicates_defined_on` is used (on
+ // an external item) is for traits, during chalk lowering,
+ // so only encode it in that case as an efficiency
+ // hack. (No reason not to expand it in the future if
+ // necessary.)
+ predicates_defined_on: match item.node {
+ hir::ItemTrait(..) => Some(self.encode_predicates_defined_on(def_id)),
+ _ => None, // not *wrong* for other kinds of items, but not needed
+ },
+
mir: match item.node {
hir::ItemStatic(..) => {
self.encode_optimized_mir(def_id)
variances: LazySeq::empty(),
generics: None,
predicates: None,
+ predicates_defined_on: None,
mir: None,
}
}
variances: LazySeq::empty(),
generics: None,
predicates: None,
+ predicates_defined_on: None,
mir: None,
}
variances: LazySeq::empty(),
generics: Some(self.encode_generics(def_id)),
predicates: None,
+ predicates_defined_on: None,
mir: self.encode_optimized_mir(def_id),
}
variances: LazySeq::empty(),
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
+ predicates_defined_on: None,
mir: self.encode_optimized_mir(def_id),
}
},
generics: Some(self.encode_generics(def_id)),
predicates: Some(self.encode_predicates(def_id)),
+ predicates_defined_on: None,
mir: None,
}
pub variances: LazySeq<ty::Variance>,
pub generics: Option<Lazy<ty::Generics>>,
pub predicates: Option<Lazy<ty::GenericPredicates<'tcx>>>,
+ pub predicates_defined_on: Option<Lazy<ty::GenericPredicates<'tcx>>>,
pub mir: Option<Lazy<mir::Mir<'tcx>>>,
}
variances,
generics,
predicates,
+ predicates_defined_on,
mir
});
// ```
// `FromEnv(WC) :- FromEnv(Self: Trait<P1..Pn>)`, for each where clause WC
- // FIXME: Remove the [1..] slice; this is a hack because the query
- // predicates_of currently includes the trait itself (`Self: Trait<P1..Pn>`).
- let where_clauses = &tcx.predicates_of(def_id).predicates;
- let implied_bound_clauses = where_clauses[1..]
+ let where_clauses = &tcx.predicates_defined_on(def_id).predicates;
+ let implied_bound_clauses = where_clauses
.into_iter()
.map(|wc| wc.lower())
type_of,
generics_of,
predicates_of,
+ predicates_defined_on,
explicit_predicates_of,
super_predicates_of,
type_param_predicates,
})
}
-fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
- def_id: DefId)
- -> ty::GenericPredicates<'tcx> {
- let explicit = explicit_predicates_of(tcx, def_id);
+fn predicates_defined_on<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId)
+ -> ty::GenericPredicates<'tcx> {
+ let explicit = tcx.explicit_predicates_of(def_id);
let predicates = if tcx.sess.features_untracked().infer_outlives_requirements {
[&explicit.predicates[..], &tcx.inferred_outlives_of(def_id)[..]].concat()
} else { explicit.predicates };
}
}
-pub fn explicit_predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+fn predicates_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId)
-> ty::GenericPredicates<'tcx> {
+ let ty::GenericPredicates { parent, mut predicates } =
+ tcx.predicates_defined_on(def_id);
+
+ if tcx.is_trait(def_id) {
+ // For traits, add `Self: Trait` predicate. This is
+ // not part of the predicates that a user writes, but it
+ // is something that one must prove in order to invoke a
+ // method or project an associated type.
+ //
+ // In the chalk setup, this predicate is not part of the
+ // "predicates" for a trait item. But it is useful in
+ // rustc because if you directly (e.g.) invoke a trait
+ // method like `Trait::method(...)`, you must naturally
+ // prove that the trait applies to the types that were
+ // used, and adding the predicate into this list ensures
+ // that this is done.
+ predicates.push(ty::TraitRef::identity(tcx, def_id).to_predicate());
+ }
+
+ ty::GenericPredicates { parent, predicates }
+}
+
+fn explicit_predicates_of<'a, 'tcx>(
+ tcx: TyCtxt<'a, 'tcx, 'tcx>,
+ def_id: DefId,
+) -> ty::GenericPredicates<'tcx> {
use rustc::hir::map::*;
use rustc::hir::*;
let icx = ItemCtxt::new(tcx, def_id);
let no_generics = hir::Generics::empty();
let ast_generics = match node {
- NodeTraitItem(item) => &item.generics,
+ NodeTraitItem(item) => {
+ &item.generics
+ }
+
NodeImplItem(item) => &item.generics,
NodeItem(item) => {
// and the explicit where-clauses, but to get the full set of predicates
// on a trait we need to add in the supertrait bounds and bounds found on
// associated types.
- if let Some((trait_ref, _)) = is_trait {
+ if let Some((_trait_ref, _)) = is_trait {
predicates = tcx.super_predicates_of(def_id).predicates;
-
- // Add in a predicate that `Self:Trait` (where `Trait` is the
- // current trait). This is needed for builtin bounds.
- predicates.push(trait_ref.to_poly_trait_ref().to_predicate());
}
// In default impls, we can assume that the self type implements
LL | #[rustc_dump_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
+ = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
LL | #[rustc_dump_env_program_clauses] //~ ERROR program clause dump
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
- = note: FromEnv(Self: Bar) :- FromEnv(Self: Bar).
+ = note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
= note: FromEnv(Self: Foo) :- FromEnv(Self: Bar).
= note: Implemented(Self: Bar) :- FromEnv(Self: Bar).
= note: Implemented(Self: Foo) :- FromEnv(Self: Foo).