"cannot borrow `*test` as immutable because it is also borrowed as mutable" when interacting with lifetime GATs and closures

⚓ Rust    📅 2025-10-28    👤 surdeus    👁️ 7      

surdeus

Warning

This post was published 34 days ago. The information described in this article may have changed.

Hi, I have the following code:

trait Test {
    type Category;
    type InnerType<'a> where Self::Category: 'a;
    
    fn borrow_test<'a>(&'a mut self, callback: impl FnOnce(&mut Self::InnerType<'a>));
    fn do_something_else(&self);
}

fn uses_test<'a, T: Test>(test: &'a mut T, callback: impl FnOnce(&mut T::InnerType<'a>)) {
    test.borrow_test(|test2| {
        callback(test2);
    });
    
    test.do_something_else();
}

I would expect this to compile, as the borrow_test invocation in uses_test in practice only borrows test for the duration of the function call, after which all mutable references to test will already have been dropped again.

However, I get this error:

error[E0502]: cannot borrow `*test` as immutable because it is also borrowed as mutable
  --> src/x.rs:14:5
   |
 9 | fn uses_test<'a, T: Test>(test: &'a mut T, callback: impl FnOnce(&mut T::InnerType<'a>)) {
   |              -- lifetime `'a` defined here
10 |     test.borrow_test(|test2| {
   |     ---- mutable borrow occurs here
11 |         callback(test2);
   |         --------------- argument requires that `*test` is borrowed for `'a`
...
14 |     test.do_something_else();
   |     ^^^^ immutable borrow occurs here

I have tried everything I could think of to communicate to Rust that all mutable references to test will be dropped before the do_something_else call, but except for removing the closure in uses_test and removing the lifetime GAT (both of which are necessary for the actual code i am working on), I have not been able to get this to work. Can anyone help?

3 posts - 2 participants

Read full topic

🏷️ Rust_feed