Move EarlyBinder calls in rustc_typeck::outlives a bit further up

This commit is contained in:
Jack Huey 2022-07-02 18:27:49 -04:00
parent 1517f5de01
commit f16584357d
5 changed files with 35 additions and 27 deletions

View File

@ -932,6 +932,10 @@ impl<T> EarlyBinder<T> {
let value = f(self.0)?;
Ok(EarlyBinder(value))
}
pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
EarlyBinder(value)
}
}
impl<T> EarlyBinder<Option<T>> {

View File

@ -6,7 +6,7 @@ use super::utils::*;
#[derive(Debug)]
pub struct ExplicitPredicatesMap<'tcx> {
map: FxHashMap<DefId, RequiredPredicates<'tcx>>,
map: FxHashMap<DefId, ty::EarlyBinder<RequiredPredicates<'tcx>>>,
}
impl<'tcx> ExplicitPredicatesMap<'tcx> {
@ -14,11 +14,11 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
ExplicitPredicatesMap { map: FxHashMap::default() }
}
pub fn explicit_predicates_of(
pub(crate) fn explicit_predicates_of(
&mut self,
tcx: TyCtxt<'tcx>,
def_id: DefId,
) -> &RequiredPredicates<'tcx> {
) -> &ty::EarlyBinder<RequiredPredicates<'tcx>> {
self.map.entry(def_id).or_insert_with(|| {
let predicates = if def_id.is_local() {
tcx.explicit_predicates_of(def_id)
@ -63,7 +63,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> {
}
}
required_predicates
ty::EarlyBinder(required_predicates)
})
}
}

View File

@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap;
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;
@ -13,20 +13,19 @@ use super::utils::*;
/// `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() {
@ -53,9 +52,9 @@ pub fn infer_predicates<'tcx>(
tcx,
field_ty,
field_span,
&mut global_inferred_outlives,
&global_inferred_outlives,
&mut item_required_predicates,
explicit_map,
&mut explicit_map,
);
}
}
@ -70,12 +69,17 @@ pub fn infer_predicates<'tcx>(
// 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
@ -85,7 +89,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
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>,
) {
@ -133,11 +137,13 @@ fn insert_required_predicates_to_be_wf<'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,
@ -224,7 +230,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
/// 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>],
@ -242,7 +248,7 @@ pub fn check_explicit_predicates<'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<..>`
@ -287,7 +293,7 @@ pub fn check_explicit_predicates<'tcx>(
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);
}

View File

@ -88,9 +88,7 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
// for the type.
// Compute the inferred predicates
let mut exp_map = explicit::ExplicitPredicatesMap::new();
let global_inferred_outlives = implicit_infer::infer_predicates(tcx, &mut exp_map);
let global_inferred_outlives = implicit_infer::infer_predicates(tcx);
// Convert the inferred predicates into the "collected" form the
// global data structure expects.
@ -100,7 +98,7 @@ fn inferred_outlives_crate(tcx: TyCtxt<'_>, (): ()) -> CratePredicatesMap<'_> {
let predicates = global_inferred_outlives
.iter()
.map(|(&def_id, set)| {
let predicates = &*tcx.arena.alloc_from_iter(set.iter().filter_map(
let predicates = &*tcx.arena.alloc_from_iter(set.0.iter().filter_map(
|(ty::OutlivesPredicate(kind1, region2), &span)| {
match kind1.unpack() {
GenericArgKind::Type(ty1) => Some((

View File

@ -7,12 +7,12 @@ use std::collections::BTreeMap;
/// Tracks the `T: 'a` or `'a: 'a` predicates that we have inferred
/// must be added to the struct header.
pub type RequiredPredicates<'tcx> =
pub(crate) type RequiredPredicates<'tcx> =
BTreeMap<ty::OutlivesPredicate<GenericArg<'tcx>, ty::Region<'tcx>>, Span>;
/// Given a requirement `T: 'a` or `'b: 'a`, deduce the
/// outlives_component and add it to `required_predicates`
pub fn insert_outlives_predicate<'tcx>(
pub(crate) fn insert_outlives_predicate<'tcx>(
tcx: TyCtxt<'tcx>,
kind: GenericArg<'tcx>,
outlived_region: Region<'tcx>,