|
| 1 | +//@ run-pass |
| 2 | +#![expect(incomplete_features)] |
| 3 | +#![feature(explicit_tail_calls)] |
| 4 | + |
| 5 | +// This is a classic example of mutual recursion: |
| 6 | +// even(n) calls odd(n-1), and odd(n) calls even(n-1) |
| 7 | +// Without tail calls, this would quickly overflow the stack for large inputs |
| 8 | + |
| 9 | +// Check if a number is even using mutual recursion |
| 10 | +fn is_even(n: u64) -> bool { |
| 11 | + match n { |
| 12 | + 0 => true, |
| 13 | + _ => become is_odd(n - 1) |
| 14 | + } |
| 15 | +} |
| 16 | + |
| 17 | +// Check if a number is odd using mutual recursion |
| 18 | +fn is_odd(n: u64) -> bool { |
| 19 | + match n { |
| 20 | + 0 => false, |
| 21 | + _ => become is_even(n - 1) |
| 22 | + } |
| 23 | +} |
| 24 | + |
| 25 | +// Versions without tail calls for comparison |
| 26 | +fn is_even_no_tail(n: u64) -> bool { |
| 27 | + match n { |
| 28 | + 0 => true, |
| 29 | + _ => is_odd_no_tail(n - 1) |
| 30 | + } |
| 31 | +} |
| 32 | + |
| 33 | +fn is_odd_no_tail(n: u64) -> bool { |
| 34 | + match n { |
| 35 | + 0 => false, |
| 36 | + _ => is_even_no_tail(n - 1) |
| 37 | + } |
| 38 | +} |
| 39 | + |
| 40 | +fn main() { |
| 41 | + // Verify correctness for small values |
| 42 | + assert_eq!(is_even(0), true); |
| 43 | + assert_eq!(is_odd(0), false); |
| 44 | + assert_eq!(is_even(1), false); |
| 45 | + assert_eq!(is_odd(1), true); |
| 46 | + assert_eq!(is_even(10), true); |
| 47 | + assert_eq!(is_odd(10), false); |
| 48 | + |
| 49 | + // Test with an extremely large number that would definitely overflow the stack |
| 50 | + // without tail call optimization - each call creates 2 stack frames (alternating between functions) |
| 51 | + // so 100,000 would create 200,000 stack frames total |
| 52 | + assert_eq!(is_even(100_000), true); |
| 53 | + assert_eq!(is_odd(100_000), false); |
| 54 | + assert_eq!(is_even(100_001), false); |
| 55 | + assert_eq!(is_odd(100_001), true); |
| 56 | + |
| 57 | + println!("Deep mutual recursion test passed with 100,000 alternating recursive calls!"); |
| 58 | + |
| 59 | + // Verify non-tail versions work for small values |
| 60 | + assert_eq!(is_even_no_tail(10), true); |
| 61 | + assert_eq!(is_odd_no_tail(10), false); |
| 62 | + // But would overflow for large values (not tested to avoid crashing) |
| 63 | +} |
0 commit comments