Auto merge of #150859 - nnethercote:opt-Canonicalizer-flag-checks, r=lcnr

Optimize canonicalizer flag checks.

The most important change here relates to type folding: we now check the flags up front, instead of doing it in `inner_fold_ty` after checking the cache and doing a match. This is a small perf win, and matches other similar folders (e.g. `CanonicalInstantiator`).

Likewise for const folding, we now check the flags first. (There is no cache for const folding.)

Elsewhere we don't check flags before folding a predicate (unnecessary, because `fold_predicate` already checks the flags itself before doing anything else), and invert the flag checks in a couple of methods to match the standard order.

r? @lcnr
This commit is contained in:
bors
2026-01-13 17:36:45 +00:00
@@ -221,16 +221,12 @@ pub(super) fn canonicalize_input<P: TypeFoldable<I>>(
};
let predicate = input.goal.predicate;
let predicate = if predicate.has_type_flags(NEEDS_CANONICAL) {
predicate.fold_with(&mut rest_canonicalizer)
} else {
predicate
};
let predicate = predicate.fold_with(&mut rest_canonicalizer);
let goal = Goal { param_env, predicate };
let predefined_opaques_in_body = input.predefined_opaques_in_body;
let predefined_opaques_in_body =
if input.predefined_opaques_in_body.has_type_flags(NEEDS_CANONICAL) {
if predefined_opaques_in_body.has_type_flags(NEEDS_CANONICAL) {
predefined_opaques_in_body.fold_with(&mut rest_canonicalizer)
} else {
predefined_opaques_in_body
@@ -397,11 +393,7 @@ fn inner_fold_ty(&mut self, t: I::Ty) -> I::Ty {
| ty::Alias(_, _)
| ty::Bound(_, _)
| ty::Error(_) => {
return if t.has_type_flags(NEEDS_CANONICAL) {
ensure_sufficient_stack(|| t.super_fold_with(self))
} else {
t
};
return ensure_sufficient_stack(|| t.super_fold_with(self));
}
};
@@ -483,7 +475,9 @@ fn fold_region(&mut self, r: I::Region) -> I::Region {
}
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
if let Some(&ty) = self.cache.get(&t) {
if !t.flags().intersects(NEEDS_CANONICAL) {
t
} else if let Some(&ty) = self.cache.get(&t) {
ty
} else {
let res = self.inner_fold_ty(t);
@@ -494,6 +488,10 @@ fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
}
fn fold_const(&mut self, c: I::Const) -> I::Const {
if !c.flags().intersects(NEEDS_CANONICAL) {
return c;
}
let kind = match c.kind() {
ty::ConstKind::Infer(i) => match i {
ty::InferConst::Var(vid) => {
@@ -533,9 +531,7 @@ fn fold_const(&mut self, c: I::Const) -> I::Const {
| ty::ConstKind::Unevaluated(_)
| ty::ConstKind::Value(_)
| ty::ConstKind::Error(_)
| ty::ConstKind::Expr(_) => {
return if c.has_type_flags(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c };
}
| ty::ConstKind::Expr(_) => return c.super_fold_with(self),
};
let var = self.get_or_insert_bound_var(c, kind);
@@ -544,7 +540,7 @@ fn fold_const(&mut self, c: I::Const) -> I::Const {
}
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
if p.flags().intersects(NEEDS_CANONICAL) { p.super_fold_with(self) } else { p }
if !p.flags().intersects(NEEDS_CANONICAL) { p } else { p.super_fold_with(self) }
}
fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
@@ -555,6 +551,6 @@ fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
panic!("erasing 'static in env")
}
}
if c.flags().intersects(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c }
if !c.flags().intersects(NEEDS_CANONICAL) { c } else { c.super_fold_with(self) }
}
}