I've been checking out the practice.rs exercises and in one of them I discovered something strange. I found out that the order if lifetime arguments in the struct declaration matters for the successful compilation. That is struct S<'a, 'b> produces different results from struct S<'b, 'a>.
And if I swap the Interface struct lifetime arguments: struct Interface<'a, 'r> the code ceases to compile. So it looks like there is some hidden constraints are introduced, but I haven't been able to google anything specific about this.
Does anyone know why this order changes the compiler behavior?
Of course it matters. &'a mut T<'b> is not the same as &'b mut T<'a> (given that the two lifetimes differ). &'b mut T<'a> doesn't make sense if 'a is shorter than 'b, because the mutable reference is then dangling.
That goes without saying, but in my example the field of the Interface didn't change, it's still manager: &'r mut Manager<'a>, only the order of the lifetime args changes from 'r, 'a to 'a, 'r which to my understanding shouldn't have changed anything substantially.
So the first lifetime parameter of Interface is how long lives the borrow ofList, and the second one is how long lives the borrow insideList. This necessarily requires that 'list is not longer then 'a - otherwise the referenced List would have a dangling borrow.
Now, moving to the struct declaration: you have &'r mut Manager<'a>, and by the same logic, 'r is not longer then 'a.
In your original code, these two descriptions align with each other: 'list is passed in place of 'r, 'a - in place of 'a; everything works.
After swapping parameter order, however, you get 'list in place of 'a and 'a in place of 'r. Therefore, combining two requirements above, we essentially force 'r and 'a (or, alternatively, 'list and 'a) to be exactly the same, i.e. once you call get_interface, List (and Interface with it) is locked forever.