Skip to content

Commit 9c0bcb5

Browse files
committed
Auto merge of rust-lang#141442 - compiler-errors:fast-path-pred, r=lcnr
Fold predicate fast path in canonicalizer and eager resolver See individual commits. r? lcnr
2 parents b5eb989 + ade2435 commit 9c0bcb5

File tree

3 files changed

+59
-8
lines changed

3 files changed

+59
-8
lines changed

compiler/rustc_infer/src/infer/canonical/canonicalizer.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,10 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
493493
ct
494494
}
495495
}
496+
497+
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
498+
if p.flags().intersects(self.needs_canonical_flags) { p.super_fold_with(self) } else { p }
499+
}
496500
}
497501

498502
impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {

compiler/rustc_next_trait_solver/src/canonicalizer.rs

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,22 @@ use rustc_type_ir::data_structures::{HashMap, ensure_sufficient_stack};
44
use rustc_type_ir::inherent::*;
55
use rustc_type_ir::solve::{Goal, QueryInput};
66
use rustc_type_ir::{
7-
self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, InferCtxtLike, Interner,
8-
TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
7+
self as ty, Canonical, CanonicalTyVarKind, CanonicalVarKind, Flags, InferCtxtLike, Interner,
8+
TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
99
};
1010

1111
use crate::delegate::SolverDelegate;
1212

13+
/// Does this have infer/placeholder/param, free regions or ReErased?
14+
const NEEDS_CANONICAL: TypeFlags = TypeFlags::from_bits(
15+
TypeFlags::HAS_INFER.bits()
16+
| TypeFlags::HAS_PLACEHOLDER.bits()
17+
| TypeFlags::HAS_PARAM.bits()
18+
| TypeFlags::HAS_FREE_REGIONS.bits()
19+
| TypeFlags::HAS_RE_ERASED.bits(),
20+
)
21+
.unwrap();
22+
1323
/// Whether we're canonicalizing a query input or the query response.
1424
///
1525
/// When canonicalizing an input we're in the context of the caller
@@ -79,7 +89,11 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
7989
cache: Default::default(),
8090
};
8191

82-
let value = value.fold_with(&mut canonicalizer);
92+
let value = if value.has_type_flags(NEEDS_CANONICAL) {
93+
value.fold_with(&mut canonicalizer)
94+
} else {
95+
value
96+
};
8397
assert!(!value.has_infer(), "unexpected infer in {value:?}");
8498
assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
8599
let (max_universe, variables) = canonicalizer.finalize();
@@ -111,7 +125,14 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
111125

112126
cache: Default::default(),
113127
};
114-
let param_env = input.goal.param_env.fold_with(&mut env_canonicalizer);
128+
129+
let param_env = input.goal.param_env;
130+
let param_env = if param_env.has_type_flags(NEEDS_CANONICAL) {
131+
param_env.fold_with(&mut env_canonicalizer)
132+
} else {
133+
param_env
134+
};
135+
115136
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
116137
// Then canonicalize the rest of the input without keeping `'static`
117138
// while *mostly* reusing the canonicalizer from above.
@@ -134,10 +155,22 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
134155
cache: Default::default(),
135156
};
136157

137-
let predicate = input.goal.predicate.fold_with(&mut rest_canonicalizer);
158+
let predicate = input.goal.predicate;
159+
let predicate = if predicate.has_type_flags(NEEDS_CANONICAL) {
160+
predicate.fold_with(&mut rest_canonicalizer)
161+
} else {
162+
predicate
163+
};
138164
let goal = Goal { param_env, predicate };
165+
166+
let predefined_opaques_in_body = input.predefined_opaques_in_body;
139167
let predefined_opaques_in_body =
140-
input.predefined_opaques_in_body.fold_with(&mut rest_canonicalizer);
168+
if input.predefined_opaques_in_body.has_type_flags(NEEDS_CANONICAL) {
169+
predefined_opaques_in_body.fold_with(&mut rest_canonicalizer)
170+
} else {
171+
predefined_opaques_in_body
172+
};
173+
141174
let value = QueryInput { goal, predefined_opaques_in_body };
142175

143176
assert!(!value.has_infer(), "unexpected infer in {value:?}");
@@ -387,7 +420,11 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
387420
| ty::Alias(_, _)
388421
| ty::Bound(_, _)
389422
| ty::Error(_) => {
390-
return ensure_sufficient_stack(|| t.super_fold_with(self));
423+
return if t.has_type_flags(NEEDS_CANONICAL) {
424+
ensure_sufficient_stack(|| t.super_fold_with(self))
425+
} else {
426+
t
427+
};
391428
}
392429
};
393430

@@ -522,11 +559,17 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
522559
| ty::ConstKind::Unevaluated(_)
523560
| ty::ConstKind::Value(_)
524561
| ty::ConstKind::Error(_)
525-
| ty::ConstKind::Expr(_) => return c.super_fold_with(self),
562+
| ty::ConstKind::Expr(_) => {
563+
return if c.has_type_flags(NEEDS_CANONICAL) { c.super_fold_with(self) } else { c };
564+
}
526565
};
527566

528567
let var = self.get_or_insert_bound_var(c, kind);
529568

530569
Const::new_anon_bound(self.cx(), self.binder_index, var)
531570
}
571+
572+
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
573+
if p.flags().intersects(NEEDS_CANONICAL) { p.super_fold_with(self) } else { p }
574+
}
532575
}

compiler/rustc_next_trait_solver/src/resolve.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,8 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for EagerResolv
8686
}
8787
}
8888
}
89+
90+
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
91+
if p.has_infer() { p.super_fold_with(self) } else { p }
92+
}
8993
}

0 commit comments

Comments
 (0)