I cannot be sure but this seems like a problem to me. And unnecessary as well.
If I understand your top level struct has some kind of stack of structs as a member which it passes to itself, via "self", all the way down the recursive rabbit hole.
Why do that? Why not make use of the processor stack you are using anyway and comes for free. Instead of putting those structs on a stack that you are maintaining yourself just create new ones locally at each recursion level and pass them as parameters. The recursive calls will then create and destroy them as they are made automatically.
I have no idea if that is at all helpful. Just thinking aloud.
Meanwhile I have this horribly recursive calculation with it's associated data structures that I was surprised to find gave no cause for the borrow checker to fight me, maybe there is some inspiration in there somewhere:
const PNUM: usize = 1300;
const FNUM: usize = 10;
const SMAX: i64 = 100_000_000;
struct Primes {
primes: Vec<i64>,
}
impl Primes {
fn new() -> Primes {
let mut primes = Primes {
primes: vec![0; PNUM],
};
let mut p: i64;
let mut r: i64;
primes.primes[0] = 2;
primes.primes[1] = 3;
let mut pn: i64 = 2;
let mut in_: i64 = 1;
fn isprime(p: i64, in_: &mut i64, primes: &[i64]) -> bool {
for i in 1..*in_ {
if p % primes[i as usize] == 0 {
return false;
}
}
let mut i = *in_;
while primes[i as usize] * primes[i as usize] <= p {
if p % primes[i as usize] == 0 {
return false;
}
i += 1;
}
*in_ = i - 1;
true
}
p = 5;
while pn < PNUM as i64 {
if isprime(p, &mut in_, &primes.primes) {
primes.primes[pn as usize] = p;
pn += 1;
}
p += 2;
}
if p <= SMAX / p + 1 {
panic!("The maximum prime {} is too small!", p);
}
r = 1;
for i in 0..(FNUM - 1) {
if primes.primes[i] > SMAX / r + 1 {
return primes;
}
r *= primes.primes[i];
}
panic!("Distinct primes {} in factorisation too few!", FNUM);
}
}
struct Factors {
s: i64,
fmax: i64,
i: i64,
p: Vec<i64>,
n: Vec<i64>,
}
impl Factors {
fn new(size: usize) -> Factors {
Factors {
s: 2,
fmax: 0,
i: 0,
p: vec![0; size],
n: vec![0; size],
}
}
}
struct Tatami {
isn: i64,
factors: Factors,
primes: Primes,
smin: i64,
z: Vec<i64>,
}
impl Tatami {
fn new(primes: Primes) -> Tatami {
Tatami {
isn: 0,
factors: Factors::new(FNUM),
primes,
smin: SMAX + 2,
z: vec![0; FNUM],
}
}
fn sigma(&mut self) -> i64 {
let mut r = self.factors.n[0];
for i in 1..=self.factors.fmax {
r *= self.factors.n[i as usize] + 1;
}
r
}
fn free(&mut self, k: i64, l: i64) -> bool {
let n: i64 = l / k;
let lmin: i64 = (k + 1) * n + 2;
let lmax: i64 = (k - 1) * (n + 1) - 2;
(lmin <= l) && (l <= lmax)
}
fn t(&mut self) -> i64 {
let mut r = 0;
loop {
let mut found: bool = false;
for i in 0..=self.factors.fmax {
if self.z[i as usize] < self.factors.n[i as usize] {
self.z[i as usize] += 1;
found = true;
break;
}
self.z[i as usize] = 0;
}
if !found {
break;
}
let mut k = 1;
let mut l = 1;
for i in 0..=self.factors.fmax {
k *= self.factors.p[i as usize].pow(self.z[i as usize] as u32);
l *= self.factors.p[i as usize]
.pow(self.factors.n[i as usize] as u32 - self.z[i as usize] as u32);
}
if k <= l {
r += self.free(k, l) as i64;
}
}
r
}
fn work(&mut self) {
let s = self.factors.s;
let mut r = self.sigma();
if r >= self.isn {
r = self.t();
if (r == self.isn) && (s < self.smin) {
self.smin = s;
}
}
let mut fmax = self.factors.fmax as usize;
let pmax = SMAX / s + 1;
let i = self.factors.i;
let mut p = self.primes.primes[i as usize];
if p <= pmax {
self.factors.n[fmax] += 1;
self.factors.s = s * p;
self.work();
self.factors.n[fmax] -= 1;
}
fmax += 1;
self.factors.n[fmax] = 1;
for j in i + 1..PNUM as i64 {
p = self.primes.primes[j as usize];
if p > pmax {
break;
}
self.factors.p[fmax] = p;
self.factors.s = s * p;
self.factors.i = j;
self.factors.fmax = fmax as i64;
self.work();
}
self.factors.n[fmax] = 0;
}
fn inv(&mut self, n: i64) -> i64 {
self.isn = n;
self.factors = Factors::new(FNUM);
self.factors.p[0] = self.primes.primes[0];
self.factors.n[0] = 1;
self.factors.i = 0;
self.factors.s = 2;
self.factors.fmax = 0;
self.work();
if self.smin < SMAX {
self.smin
} else {
-1
}
}
}
fn main() {
let n = 200;
let primes = Primes::new();
let mut tatami = Tatami::new(primes);
println!("T({})={}", tatami.inv(n), n);
}