Expand description
Unified recursion guard for cycle detection, depth limiting, and iteration bounding in recursive type computations.
§Design
RecursionGuard replaces the scattered in_progress / visiting / depth /
total_checks fields that were manually reimplemented across SubtypeChecker,
TypeEvaluator, PropertyAccessEvaluator, and others.
It combines three safety mechanisms:
- Cycle detection via a visiting set (
FxHashSet<K>) - Depth limiting to prevent stack overflow
- Iteration bounding to prevent infinite loops
§Profiles
RecursionProfile provides named presets that eliminate magic numbers and
make the intent of each guard clear at the call site:
ⓘ
// Before (what does 50, 100_000 mean?)
let guard = RecursionGuard::new(50, 100_000);
// After (intent is clear, limits are centralized)
let guard = RecursionGuard::with_profile(RecursionProfile::TypeEvaluation);§Safety
- Debug leak detection: In debug builds, dropping a guard with active entries
triggers a panic, catching forgotten
leave()calls. - Debug double-leave detection: In debug builds, leaving a key that isn’t in the visiting set triggers a panic.
- Overflow protection: Iteration counting uses saturating arithmetic.
- Encapsulated exceeded state: The
exceededflag is private; useis_exceeded()andmark_exceeded().
Structs§
- Depth
Counter - A lightweight depth counter for stack overflow protection.
- Recursion
Guard - Tracks recursion state for cycle detection, depth limiting, and iteration bounding.
Enums§
- Recursion
Profile - Named recursion limit presets.
- Recursion
Result - Result of attempting to enter a recursive computation.