Skip to content

Commit bd36e69

Browse files
committed
Auto merge of rust-lang#133566 - lcnr:fast-reject-perf, r=compiler-errors
fast-reject: add cache slightly modified version of rust-lang#133524 I tried a few alternatives: - simply bail after recursion for a certain amount of times, however, looking at the number of steps taken while compiling different crates we get the following results[^1]: - add a cache: results in a bigger performance impact typenum ```rust 1098842 counts ( 1) 670511 (61.0%, 61.0%): dropping after 1 ( 2) 358785 (32.7%, 93.7%): dropping after 0 ( 3) 25191 ( 2.3%, 96.0%): dropping after 2 ( 4) 10912 ( 1.0%, 97.0%): dropping after 4 ( 5) 6461 ( 0.6%, 97.5%): dropping after 3 ( 6) 5239 ( 0.5%, 98.0%): dropping after 5 ( 7) 2528 ( 0.2%, 98.3%): dropping after 8 ( 8) 2188 ( 0.2%, 98.5%): dropping after 1094 ( 9) 2097 ( 0.2%, 98.6%): dropping after 6 ( 10) 1179 ( 0.1%, 98.7%): dropping after 34 ( 11) 1148 ( 0.1%, 98.9%): dropping after 7 ( 12) 822 ( 0.1%, 98.9%): dropping after 10 ``` bitmaps ```rust 533346 counts ( 1) 526166 (98.7%, 98.7%): dropping after 1 ( 2) 4562 ( 0.9%, 99.5%): dropping after 0 ( 3) 2072 ( 0.4%, 99.9%): dropping after 1024 ( 4) 305 ( 0.1%,100.0%): dropping after 2 ( 5) 106 ( 0.0%,100.0%): dropping after 4 ( 6) 30 ( 0.0%,100.0%): dropping after 8 ( 7) 18 ( 0.0%,100.0%): dropping after 3 ( 8) 17 ( 0.0%,100.0%): dropping after 44 ( 9) 15 ( 0.0%,100.0%): dropping after 168 ( 10) 8 ( 0.0%,100.0%): dropping after 14 ( 11) 7 ( 0.0%,100.0%): dropping after 13 ( 12) 7 ( 0.0%,100.0%): dropping after 24 ``` stage 2 compiler is mostly trivial, but has a few cases where we get >5000 ```rust 12987156 counts ( 1) 9280476 (71.5%, 71.5%): dropping after 0 ( 2) 2277841 (17.5%, 89.0%): dropping after 1 ( 3) 724888 ( 5.6%, 94.6%): dropping after 2 ( 4) 204005 ( 1.6%, 96.2%): dropping after 4 ( 5) 146537 ( 1.1%, 97.3%): dropping after 3 ( 6) 64287 ( 0.5%, 97.8%): dropping after 5 ( 7) 43938 ( 0.3%, 98.1%): dropping after 6 ( 8) 43758 ( 0.3%, 98.4%): dropping after 8 ( 9) 27220 ( 0.2%, 98.7%): dropping after 7 ( 10) 17374 ( 0.1%, 98.8%): dropping after 9 ( 11) 16015 ( 0.1%, 98.9%): dropping after 10 ( 12) 12855 ( 0.1%, 99.0%): dropping after 12 ( 13) 10494 ( 0.1%, 99.1%): dropping after 11 ( 14) 7553 ( 0.1%, 99.2%): dropping after 14 ``` [^1]: i've incremented a counter in the place I now decrement the depth at and then printed it on drop r? `@compiler-errors`
2 parents caa8172 + 3465ce5 commit bd36e69

File tree

1 file changed

+53
-17
lines changed

1 file changed

+53
-17
lines changed

compiler/rustc_type_ir/src/fast_reject.rs

+53-17
Original file line numberDiff line numberDiff line change
@@ -214,27 +214,47 @@ impl<I: Interner> DeepRejectCtxt<I, false, true> {
214214
impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_WITH_INFER: bool>
215215
DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER>
216216
{
217+
// Quite arbitrary. Large enough to only affect a very tiny amount of impls/crates
218+
// and small enough to prevent hangs.
219+
const STARTING_DEPTH: usize = 8;
220+
217221
pub fn args_may_unify(
218222
self,
219223
obligation_args: I::GenericArgs,
220224
impl_args: I::GenericArgs,
221225
) -> bool {
226+
self.args_may_unify_inner(obligation_args, impl_args, Self::STARTING_DEPTH)
227+
}
228+
229+
pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool {
230+
self.types_may_unify_inner(lhs, rhs, Self::STARTING_DEPTH)
231+
}
232+
233+
fn args_may_unify_inner(
234+
self,
235+
obligation_args: I::GenericArgs,
236+
impl_args: I::GenericArgs,
237+
depth: usize,
238+
) -> bool {
239+
// No need to decrement the depth here as this function is only
240+
// recursively reachable via `types_may_unify_inner` which already
241+
// increments the depth for us.
222242
iter::zip(obligation_args.iter(), impl_args.iter()).all(|(obl, imp)| {
223243
match (obl.kind(), imp.kind()) {
224244
// We don't fast reject based on regions.
225245
(ty::GenericArgKind::Lifetime(_), ty::GenericArgKind::Lifetime(_)) => true,
226246
(ty::GenericArgKind::Type(obl), ty::GenericArgKind::Type(imp)) => {
227-
self.types_may_unify(obl, imp)
247+
self.types_may_unify_inner(obl, imp, depth)
228248
}
229249
(ty::GenericArgKind::Const(obl), ty::GenericArgKind::Const(imp)) => {
230-
self.consts_may_unify(obl, imp)
250+
self.consts_may_unify_inner(obl, imp)
231251
}
232252
_ => panic!("kind mismatch: {obl:?} {imp:?}"),
233253
}
234254
})
235255
}
236256

237-
pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool {
257+
fn types_may_unify_inner(self, lhs: I::Ty, rhs: I::Ty, depth: usize) -> bool {
238258
match rhs.kind() {
239259
// Start by checking whether the `rhs` type may unify with
240260
// pretty much everything. Just return `true` in that case.
@@ -273,18 +293,31 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
273293
| ty::Placeholder(_) => {}
274294
};
275295

296+
// The type system needs to support exponentially large types
297+
// as long as they are self-similar. While most other folders
298+
// use caching to handle them, this folder exists purely as a
299+
// perf optimization and is incredibly hot. In pretty much all
300+
// uses checking the cache is slower than simply recursing, so
301+
// we instead just add an arbitrary depth cutoff.
302+
//
303+
// We only decrement the depth here as the match on `rhs`
304+
// does not recurse.
305+
let Some(depth) = depth.checked_sub(1) else {
306+
return true;
307+
};
308+
276309
// For purely rigid types, use structural equivalence.
277310
match lhs.kind() {
278311
ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() {
279312
ty::Ref(_, rhs_ty, rhs_mutbl) => {
280-
lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty)
313+
lhs_mutbl == rhs_mutbl && self.types_may_unify_inner(lhs_ty, rhs_ty, depth)
281314
}
282315
_ => false,
283316
},
284317

285318
ty::Adt(lhs_def, lhs_args) => match rhs.kind() {
286319
ty::Adt(rhs_def, rhs_args) => {
287-
lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args)
320+
lhs_def == rhs_def && self.args_may_unify_inner(lhs_args, rhs_args, depth)
288321
}
289322
_ => false,
290323
},
@@ -326,27 +359,28 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
326359
ty::Tuple(rhs) => {
327360
lhs.len() == rhs.len()
328361
&& iter::zip(lhs.iter(), rhs.iter())
329-
.all(|(lhs, rhs)| self.types_may_unify(lhs, rhs))
362+
.all(|(lhs, rhs)| self.types_may_unify_inner(lhs, rhs, depth))
330363
}
331364
_ => false,
332365
},
333366

334367
ty::Array(lhs_ty, lhs_len) => match rhs.kind() {
335368
ty::Array(rhs_ty, rhs_len) => {
336-
self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len)
369+
self.types_may_unify_inner(lhs_ty, rhs_ty, depth)
370+
&& self.consts_may_unify_inner(lhs_len, rhs_len)
337371
}
338372
_ => false,
339373
},
340374

341375
ty::RawPtr(lhs_ty, lhs_mutbl) => match rhs.kind() {
342376
ty::RawPtr(rhs_ty, rhs_mutbl) => {
343-
lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty)
377+
lhs_mutbl == rhs_mutbl && self.types_may_unify_inner(lhs_ty, rhs_ty, depth)
344378
}
345379
_ => false,
346380
},
347381

348382
ty::Slice(lhs_ty) => {
349-
matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify(lhs_ty, rhs_ty))
383+
matches!(rhs.kind(), ty::Slice(rhs_ty) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth))
350384
}
351385

352386
ty::Dynamic(lhs_preds, ..) => {
@@ -366,7 +400,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
366400
lhs_hdr == rhs_hdr
367401
&& lhs_sig_tys.len() == rhs_sig_tys.len()
368402
&& iter::zip(lhs_sig_tys.iter(), rhs_sig_tys.iter())
369-
.all(|(lhs, rhs)| self.types_may_unify(lhs, rhs))
403+
.all(|(lhs, rhs)| self.types_may_unify_inner(lhs, rhs, depth))
370404
}
371405
_ => false,
372406
},
@@ -375,49 +409,51 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
375409

376410
ty::FnDef(lhs_def_id, lhs_args) => match rhs.kind() {
377411
ty::FnDef(rhs_def_id, rhs_args) => {
378-
lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
412+
lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
379413
}
380414
_ => false,
381415
},
382416

383417
ty::Closure(lhs_def_id, lhs_args) => match rhs.kind() {
384418
ty::Closure(rhs_def_id, rhs_args) => {
385-
lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
419+
lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
386420
}
387421
_ => false,
388422
},
389423

390424
ty::CoroutineClosure(lhs_def_id, lhs_args) => match rhs.kind() {
391425
ty::CoroutineClosure(rhs_def_id, rhs_args) => {
392-
lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
426+
lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
393427
}
394428
_ => false,
395429
},
396430

397431
ty::Coroutine(lhs_def_id, lhs_args) => match rhs.kind() {
398432
ty::Coroutine(rhs_def_id, rhs_args) => {
399-
lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
433+
lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
400434
}
401435
_ => false,
402436
},
403437

404438
ty::CoroutineWitness(lhs_def_id, lhs_args) => match rhs.kind() {
405439
ty::CoroutineWitness(rhs_def_id, rhs_args) => {
406-
lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args)
440+
lhs_def_id == rhs_def_id && self.args_may_unify_inner(lhs_args, rhs_args, depth)
407441
}
408442
_ => false,
409443
},
410444

411445
ty::Pat(lhs_ty, _) => {
412446
// FIXME(pattern_types): take pattern into account
413-
matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify(lhs_ty, rhs_ty))
447+
matches!(rhs.kind(), ty::Pat(rhs_ty, _) if self.types_may_unify_inner(lhs_ty, rhs_ty, depth))
414448
}
415449

416450
ty::Error(..) => true,
417451
}
418452
}
419453

420-
pub fn consts_may_unify(self, lhs: I::Const, rhs: I::Const) -> bool {
454+
// Unlike `types_may_unify_inner`, this does not take a depth as
455+
// we never recurse from this function.
456+
fn consts_may_unify_inner(self, lhs: I::Const, rhs: I::Const) -> bool {
421457
match rhs.kind() {
422458
ty::ConstKind::Param(_) => {
423459
if INSTANTIATE_RHS_WITH_INFER {

0 commit comments

Comments
 (0)