use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
-use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
use super::explicit::ExplicitPredicatesMap;
/// `global_inferred_outlives`: this is initially the empty map that
/// was generated by walking the items in the crate. This will
/// now be filled with inferred predicates.
-pub fn infer_predicates<'tcx>(
+pub(super) fn infer_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
- explicit_map: &mut ExplicitPredicatesMap<'tcx>,
-) -> FxHashMap<DefId, RequiredPredicates<'tcx>> {
+) -> FxHashMap<DefId, ty::EarlyBinder<RequiredPredicates<'tcx>>> {
debug!("infer_predicates");
- let mut predicates_added = true;
+ let mut explicit_map = ExplicitPredicatesMap::new();
let mut global_inferred_outlives = FxHashMap::default();
// If new predicates were added then we need to re-calculate
// all crates since there could be new implied predicates.
- while predicates_added {
- predicates_added = false;
+ 'outer: loop {
+ let mut predicates_added = false;
// Visit all the crates and infer predicates
for id in tcx.hir().items() {
tcx,
field_ty,
field_span,
- &mut global_inferred_outlives,
+ &global_inferred_outlives,
&mut item_required_predicates,
- explicit_map,
+ &mut explicit_map,
);
}
}
// we walk the crates again and re-calculate predicates for all
// items.
let item_predicates_len: usize =
- global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.len());
+ global_inferred_outlives.get(&item_did.to_def_id()).map_or(0, |p| p.0.len());
if item_required_predicates.len() > item_predicates_len {
predicates_added = true;
- global_inferred_outlives.insert(item_did.to_def_id(), item_required_predicates);
+ global_inferred_outlives
+ .insert(item_did.to_def_id(), ty::EarlyBinder(item_required_predicates));
}
}
+
+ if !predicates_added {
+ break 'outer;
+ }
}
global_inferred_outlives
tcx: TyCtxt<'tcx>,
field_ty: Ty<'tcx>,
field_span: Span,
- global_inferred_outlives: &FxHashMap<DefId, RequiredPredicates<'tcx>>,
+ global_inferred_outlives: &FxHashMap<DefId, ty::EarlyBinder<RequiredPredicates<'tcx>>>,
required_predicates: &mut RequiredPredicates<'tcx>,
explicit_map: &mut ExplicitPredicatesMap<'tcx>,
) {
// 'a` holds for `Foo`.
debug!("Adt");
if let Some(unsubstituted_predicates) = global_inferred_outlives.get(&def.did()) {
- for (unsubstituted_predicate, &span) in unsubstituted_predicates {
+ for (unsubstituted_predicate, &span) in &unsubstituted_predicates.0 {
// `unsubstituted_predicate` is `U: 'b` in the
// example above. So apply the substitution to
// get `T: 'a` (or `predicate`):
- let predicate = EarlyBinder(*unsubstituted_predicate).subst(tcx, substs);
+ let predicate = unsubstituted_predicates
+ .rebind(*unsubstituted_predicate)
+ .subst(tcx, substs);
insert_outlives_predicate(
tcx,
predicate.0,
/// will give us `U: 'static` and `U: Foo`. The latter we
/// can ignore, but we will want to process `U: 'static`,
/// applying the substitution as above.
-pub fn check_explicit_predicates<'tcx>(
+fn check_explicit_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
substs: &[GenericArg<'tcx>],
);
let explicit_predicates = explicit_map.explicit_predicates_of(tcx, def_id);
- for (outlives_predicate, &span) in explicit_predicates {
+ for (outlives_predicate, &span) in &explicit_predicates.0 {
debug!("outlives_predicate = {:?}", &outlives_predicate);
// Careful: If we are inferring the effects of a `dyn Trait<..>`
continue;
}
- let predicate = EarlyBinder(*outlives_predicate).subst(tcx, substs);
+ let predicate = explicit_predicates.rebind(*outlives_predicate).subst(tcx, substs);
debug!("predicate = {:?}", &predicate);
insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates);
}