1
Fork 0

Fast path that skips over unchanged obligations in process_obligations

- only borrow the refcell once per loop
- avoid complex matches to reduce branch paths in the hot loop
- use a by-ref fast path that avoids mutations at the expense of having false negatives
This commit is contained in:
The 8472 2023-03-06 15:07:02 +01:00
parent 03b01c5bec
commit 7cce618d18
6 changed files with 79 additions and 6 deletions

View file

@ -187,6 +187,16 @@ impl<'tcx> InferCtxtInner<'tcx> {
self.projection_cache.with_log(&mut self.undo_log)
}
#[inline]
fn try_type_variables_probe_ref(
&self,
vid: ty::TyVid,
) -> Option<&type_variable::TypeVariableValue<'tcx>> {
// Uses a read-only view of the unification table, this way we don't
// need an undo log.
self.type_variable_storage.eq_relations_ref().try_probe_value(vid)
}
#[inline]
fn type_variables(&mut self) -> type_variable::TypeVariableTable<'_, 'tcx> {
self.type_variable_storage.with_log(&mut self.undo_log)
@ -1646,6 +1656,28 @@ impl<'tcx> InferCtxt<'tcx> {
tcx.const_eval_resolve_for_typeck(param_env_erased, unevaluated, span)
}
/// The returned function is used in a fast path. If it returns `true` the variable is
/// unchanged, `false` indicates that the status is unknown.
#[inline]
pub fn is_ty_infer_var_definitely_unchanged<'a>(
&'a self,
) -> (impl Fn(TyOrConstInferVar<'tcx>) -> bool + 'a) {
// This hoists the borrow/release out of the loop body.
let inner = self.inner.try_borrow();
return move |infer_var: TyOrConstInferVar<'tcx>| match (infer_var, &inner) {
(TyOrConstInferVar::Ty(ty_var), Ok(inner)) => {
use self::type_variable::TypeVariableValue;
match inner.try_type_variables_probe_ref(ty_var) {
Some(TypeVariableValue::Unknown { .. }) => true,
_ => false,
}
}
_ => false,
};
}
/// `ty_or_const_infer_var_changed` is equivalent to one of these two:
/// * `shallow_resolve(ty) != ty` (where `ty.kind = ty::Infer(_)`)
/// * `shallow_resolve(ct) != ct` (where `ct.kind = ty::ConstKind::Infer(_)`)

View file

@ -190,6 +190,11 @@ impl<'tcx> TypeVariableStorage<'tcx> {
) -> TypeVariableTable<'a, 'tcx> {
TypeVariableTable { storage: self, undo_log }
}
#[inline]
pub(crate) fn eq_relations_ref(&self) -> &ut::UnificationTableStorage<TyVidEqKey<'tcx>> {
&self.eq_relations
}
}
impl<'tcx> TypeVariableTable<'_, 'tcx> {