Skip to content

Commit 9b9d2af

Browse files
committed
Auto merge of #64545 - nnethercote:ObligForest-more, r=nmatsakis
More `ObligationForest` improvements Following on from #64500, these commits alsomake the code both nicer and faster. r? @nikomatsakis
2 parents 19d0703 + 3b85597 commit 9b9d2af

File tree

4 files changed

+139
-118
lines changed

4 files changed

+139
-118
lines changed

src/librustc/infer/mod.rs

+38-6
Original file line numberDiff line numberDiff line change
@@ -1562,11 +1562,7 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
15621562
ShallowResolver { infcx }
15631563
}
15641564

1565-
// We have this force-inlined variant of `shallow_resolve` for the one
1566-
// callsite that is extremely hot. All other callsites use the normal
1567-
// variant.
1568-
#[inline(always)]
1569-
pub fn inlined_shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
1565+
pub fn shallow_resolve(&mut self, typ: Ty<'tcx>) -> Ty<'tcx> {
15701566
match typ.sty {
15711567
ty::Infer(ty::TyVar(v)) => {
15721568
// Not entirely obvious: if `typ` is a type variable,
@@ -1601,6 +1597,42 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> {
16011597
_ => typ,
16021598
}
16031599
}
1600+
1601+
// `resolver.shallow_resolve_changed(ty)` is equivalent to
1602+
// `resolver.shallow_resolve(ty) != ty`, but more efficient. It's always
1603+
// inlined, despite being large, because it has a single call site that is
1604+
// extremely hot.
1605+
#[inline(always)]
1606+
pub fn shallow_resolve_changed(&mut self, typ: Ty<'tcx>) -> bool {
1607+
match typ.sty {
1608+
ty::Infer(ty::TyVar(v)) => {
1609+
use self::type_variable::TypeVariableValue;
1610+
1611+
// See the comment in `shallow_resolve()`.
1612+
match self.infcx.type_variables.borrow_mut().probe(v) {
1613+
TypeVariableValue::Known { value: t } => self.fold_ty(t) != typ,
1614+
TypeVariableValue::Unknown { .. } => false,
1615+
}
1616+
}
1617+
1618+
ty::Infer(ty::IntVar(v)) => {
1619+
match self.infcx.int_unification_table.borrow_mut().probe_value(v) {
1620+
Some(v) => v.to_type(self.infcx.tcx) != typ,
1621+
None => false,
1622+
}
1623+
}
1624+
1625+
ty::Infer(ty::FloatVar(v)) => {
1626+
match self.infcx.float_unification_table.borrow_mut().probe_value(v) {
1627+
Some(v) => v.to_type(self.infcx.tcx) != typ,
1628+
None => false,
1629+
}
1630+
}
1631+
1632+
_ => false,
1633+
}
1634+
}
1635+
16041636
}
16051637

16061638
impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
@@ -1609,7 +1641,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for ShallowResolver<'a, 'tcx> {
16091641
}
16101642

16111643
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
1612-
self.inlined_shallow_resolve(ty)
1644+
self.shallow_resolve(ty)
16131645
}
16141646

16151647
fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {

src/librustc/traits/fulfill.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,20 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
256256
&mut self,
257257
pending_obligation: &mut Self::Obligation,
258258
) -> ProcessResult<Self::Obligation, Self::Error> {
259-
// if we were stalled on some unresolved variables, first check
259+
// If we were stalled on some unresolved variables, first check
260260
// whether any of them have been resolved; if not, don't bother
261261
// doing more work yet
262262
if !pending_obligation.stalled_on.is_empty() {
263-
if pending_obligation.stalled_on.iter().all(|&ty| {
264-
// Use the force-inlined variant of shallow_resolve() because this code is hot.
265-
let resolved = ShallowResolver::new(self.selcx.infcx()).inlined_shallow_resolve(ty);
266-
resolved == ty // nothing changed here
267-
}) {
263+
let mut changed = false;
264+
// This `for` loop was once a call to `all()`, but this lower-level
265+
// form was a perf win. See #64545 for details.
266+
for &ty in &pending_obligation.stalled_on {
267+
if ShallowResolver::new(self.selcx.infcx()).shallow_resolve_changed(ty) {
268+
changed = true;
269+
break;
270+
}
271+
}
272+
if !changed {
268273
debug!("process_predicate: pending obligation {:?} still stalled on {:?}",
269274
self.selcx.infcx()
270275
.resolve_vars_if_possible(&pending_obligation.obligation),

src/librustc_data_structures/obligation_forest/graphviz.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,7 @@ impl<'a, O: ForestObligation + 'a> dot::GraphWalk<'a> for &'a ObligationForest<O
7474
.flat_map(|i| {
7575
let node = &self.nodes[i];
7676

77-
node.parent.iter()
78-
.chain(node.dependents.iter())
79-
.map(move |p| (p.index(), i))
77+
node.dependents.iter().map(move |&d| (d, i))
8078
})
8179
.collect()
8280
}

0 commit comments

Comments
 (0)