Auto merge of #80454 - JulianKnodt:ob_forest_op, r=matthewjasper

Skip Ty w/o infer ty/const in trait select

Remove some allocations & also add `skip_current_subtree` to skip subtrees with no inferred items.

r? `@eddyb` since marked in the FIXME
This commit is contained in:
bors 2021-02-27 17:35:35 +00:00
commit 94736c434e
2 changed files with 25 additions and 20 deletions

View File

@ -13,7 +13,7 @@ type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
pub struct TypeWalker<'tcx> {
stack: TypeWalkerStack<'tcx>,
last_subtree: usize,
visited: SsoHashSet<GenericArg<'tcx>>,
pub visited: SsoHashSet<GenericArg<'tcx>>,
}
/// An iterator for walking the type tree.

View File

@ -499,10 +499,10 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
) {
Ok(()) => ProcessResult::Changed(vec![]),
Err(ErrorHandled::TooGeneric) => {
pending_obligation.stalled_on = substs
.iter()
.filter_map(TyOrConstInferVar::maybe_from_generic_arg)
.collect();
pending_obligation.stalled_on.clear();
pending_obligation.stalled_on.extend(
substs.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
);
ProcessResult::Unchanged
}
Err(e) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(e))),
@ -544,13 +544,10 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
) {
Ok(val) => Ok(Const::from_value(self.selcx.tcx(), val, c.ty)),
Err(ErrorHandled::TooGeneric) => {
stalled_on.append(
&mut substs
stalled_on.extend(
substs
.iter()
.filter_map(|arg| {
TyOrConstInferVar::maybe_from_generic_arg(arg)
})
.collect(),
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
);
Err(ErrorHandled::TooGeneric)
}
@ -634,10 +631,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
// only reason we can fail to make progress on
// trait selection is because we don't have enough
// information about the types in the trait.
*stalled_on = substs_infer_vars(
stalled_on.clear();
stalled_on.extend(substs_infer_vars(
self.selcx,
trait_obligation.predicate.map_bound(|pred| pred.trait_ref.substs),
);
));
debug!(
"process_predicate: pending obligation {:?} now stalled on {:?}",
@ -664,10 +662,11 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
match project::poly_project_and_unify_type(self.selcx, &project_obligation) {
Ok(Ok(Some(os))) => ProcessResult::Changed(mk_pending(os)),
Ok(Ok(None)) => {
*stalled_on = substs_infer_vars(
stalled_on.clear();
stalled_on.extend(substs_infer_vars(
self.selcx,
project_obligation.predicate.map_bound(|pred| pred.projection_ty.substs),
);
));
ProcessResult::Unchanged
}
// Let the caller handle the recursion
@ -683,18 +682,24 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
fn substs_infer_vars<'a, 'tcx>(
selcx: &mut SelectionContext<'a, 'tcx>,
substs: ty::Binder<SubstsRef<'tcx>>,
) -> Vec<TyOrConstInferVar<'tcx>> {
) -> impl Iterator<Item = TyOrConstInferVar<'tcx>> {
selcx
.infcx()
.resolve_vars_if_possible(substs)
.skip_binder() // ok because this check doesn't care about regions
.iter()
// FIXME(eddyb) try using `skip_current_subtree` to skip everything that
// doesn't contain inference variables, not just the outermost level.
.filter(|arg| arg.has_infer_types_or_consts())
.flat_map(|arg| arg.walk())
.flat_map(|arg| {
let mut walker = arg.walk();
while let Some(c) = walker.next() {
if !c.has_infer_types_or_consts() {
walker.visited.remove(&c);
walker.skip_current_subtree();
}
}
walker.visited.into_iter()
})
.filter_map(TyOrConstInferVar::maybe_from_generic_arg)
.collect()
}
fn to_fulfillment_error<'tcx>(