Bound Associated Type From Another Associated Type

I'm having difficulties expressing my problem, so I'll try explaining using code comments below:

// So, I have this Runtime trait. It has a lot of associated types, one of them is Mutex.
// We can think Runtime trait as a way for me to generalize the side effect in my code.
// One obvious way to implement it is just using std::sync::Mutex for Mutex.
// But, I think this can be helpful if I want to do deterministic-simulation-testing (DST) by replacing
// the mutex and all other side effects so the effects are deterministic.
trait Runtime {
    // I have this associated type called Mutex that should implements
    // Mutex trait.
    // Now, I'm stuck at how do I express that my mutex's guard is Self::Guard.
    type Mutex<T>: Mutex<T>; 

    type Guard<'a, T: 'a>: DerefMut<Target = T>;
}

trait Mutex<T> {
    type Guard<'a>: DerefMut<Target = T>
    where
        Self: 'a;

    fn lock<'a>(&'a self) -> Self::Guard<'a>;
}

My question is on the Runtime::Mutex type. How do I express that the Mutex<T>::Guard is Self::Guard?

This bound compiles, but I’m not sure if it has exactly the semantics you need (I still don’t quite understand when for<‘a> implies ’static and when it doesn’t):

type Mutex<T>: for<'a> Mutex<T, Guard<'a>=Self::Guard<'a,T>>;

Not a direct answer to your question, but you could name the guard type through the mutex type at the use site (playground):

pub fn use_mutex<R: Runtime>(mutex: R::Mutex<usize>) -> usize {
    let guard: <R::Mutex<usize> as Mutex<usize>>::Guard<'_> = mutex.lock();
    *guard
}

Yup, this is my original solution actually. But then it's quite verbose to write, especially when I have a struct like this:

struct Page<'a, R: Runtime>
where
    R::Mutex<()>: 'a,
{
    frame: <R::Mutex<()> as Mutex<()>>::Guard<'a>,
}

I'm thinking whether I can just write R::Guard<'a, ()>

And @2e71828 's solution seems to work as expected.

If the guard were forced to live for the 'static lifetime, this would not compile:

pub fn use_mutex<R: Runtime>(mutex: R::Mutex<usize>) -> (usize, R::Mutex<usize>) {
    let val = {
      //let guard: <R::Mutex<usize> as Mutex<usize>>::Guard<'_> = mutex.lock();
      let guard: R::Guard<'_, usize> = mutex.lock();
      *guard
    };
    (val, mutex)
}

This works, but then the problem shifted to how to express the implementation:

impl Runtime for RealRuntime {
    type Mutex<T> = RealMutex<T, Self::Guard<'a, T>>; //this doesn't compile
    type Guard<'a, T: 'a> = RealGuard<'a, T>;
}

Hmm...

How about using a type synonym?

type Guard<'a, R /*: Runtime*/, T /*: 'a*/> = <<R as Runtime>::Mutex<T> as Mutex<T>>::Guard<'a>;

pub fn use_mutex<R: Runtime>(mutex: R::Mutex<usize>) -> (usize, R::Mutex<usize>) {
    let val = {
      let guard: Guard<'_, R, usize> = mutex.lock();
      //let guard: R::Guard<'_, usize> = mutex.lock();
      *guard
    };
    (val, mutex)
}

This is what I currently do. But you still need to specify the bound like this:

struct Page<'a, R: Runtime>
where
    R::Mutex<()>: 'a, // We still need this
{
    frame: Guard<'a, R, ()>, // But, thanks to type alias, this part is simpler.
}

Right, because the trait does not express that R::Mutex<T> outlives T. You could constrain T and Mutex<T> to be 'static if that is acceptable for your use-case, or introduce a lifetime for the Mutex. Not that the result is that much more readable...

No, it is limited. Having to be defined for all lifetimes (so that the HRTB can be satisfied) is not the same thing as being forced to live for 'static. (Whether that's a blocker for the OP or not is another question.)