rustc hangs on structure parameterised by lifetime and recursive trait.

2379756
Opened by Michael Rawson at 2024-12-21 04:56:52

rustc 1.62.0 (a8314ef7d 2022-06-27) stable hangs on the following snippet. Also seems to hang nightly/beta, and stuff further up the chain like rust-analyzer and clippy.

trait Recursive {
    type Recur: Recursive;
}

struct Commutes<'a, R: Recursive> {
    // so that 'a and R are used, doesn't seem important
    // can also be PhantomData<&'a R>
    _used: &'a R,

    // not related to infinite size: can be e.g. Option<Box<Commutes<...>>>
    hierarchy: Commutes<'a, <R as Recursive>::Recur>,
}

// not necessary, just for self-containment
fn main() {}

There is a genuine use-case for this pattern, but it is a bit involved. I am happy to help get this fixed, and thank you for the hard work developing the compiler! Suggestions for workarounds very welcome in the meantime.

  1. Indirection via trait with an associated type seems to work around the problem for now:

    trait Recursive {
        type Recur: Recursive;
    }
    
    // trait indirection for the recursive struct field
    trait Proxy<'a> {
        type Proxied;
    }
    
    // lifetime bound R: 'a not necessary with the natural definition
    // ...maybe this hints at something?
    impl<'a, R: 'a + Recursive> Proxy<'a> for R {
        type Proxied = Commutes<'a, R>;
    }
    
    struct Commutes<'a, R: Recursive> {
        _used: &'a R,
        // NB now needs to be boxed as the size checker kicks in
        hierarchy: Option<Box<<R::Recur as Proxy<'a>>::Proxied>>
    }
    

    Michael Rawson at 2022-08-30 08:57:57