0

I am trying to hammer in the concepts of borrowing in Rust. I know that you cannot borrow mutable references multiple times. Here I tried a bit of testing and found some peculiar scenarios I just cannot quite understand.

fn main() {
    pub fn test() {
        println!("{}", "testing success".to_string())
    };

    pub struct Test<'a> {
        pub func: &'a mut dyn FnMut() -> (),
        pub vector: &'a mut Vec<String>,
    };

    impl<'a> Test<'a> {
        pub fn repr(&self) -> String {
            format!("{}", "test".to_string())
        }
        pub fn make_clone(&'a mut self) -> Self {
            Test {
                func: self.func,
                vector: self.vector,
            }
        }
    }

    let mut test_vec = vec!["jkli".to_string(), "sadf".to_string()];
    let mut test_var = Test {
        func: &mut test,
        vector: &mut test_vec,
    };

    let mut another_test_var = Test { // <= 1st "copy" of test_var
        func: &mut test,              // <= #1 This line DOES NOT throw a mutable borrow error.
        vector: &mut test_vec,        // <= #2 This line throws a mutable borrow error as expected.
    };

    let mut new_test_var = test_var.make_clone(); // <= #3 This line also DOES NOT throw an error
                                                  // even though it should behave like the 1st "copy

    let mut last_test_var = new_test_var.make_clone();

    test_var.repr();         // <= #4 This gives an error
    another_test_var.repr();
    new_test_var.repr();     // <= #5 This gives an error as well
    last_test_var.repr();
}

Windows 10, rustc 1.47

  • I expect #4 and #5 to throw a multiple mutable borrowing error, since both structs were used to create "copies" of themselves (At least I think I understand this).
  • #2 throws an error, because I am trying to mutably reference the vector for the second time, so this should throw an error as well.
  • Why does #1 not give an error, since I am borrowing the same function each struct just like the vector?
  • Also why does #3 not throw an error? It should be identical to the first copy

Errors:

  --> src\main.rs:37:9
   |
37 |     let mut last_test_var = new_test_var.make_clone();
   |         ----^^^^^^^^^^^^^
   |         |
   |         help: remove this `mut`

error[E0499]: cannot borrow `test_vec` as mutable more than once at a time
  --> src\main.rs:31:17
   |
26 |         vector: &mut test_vec,
   |                 ------------- first mutable borrow occurs here
...
31 |         vector: &mut test_vec,        // <= #2 This line throws a mutable borrow error as expected.
   |                 ^^^^^^^^^^^^^ second mutable borrow occurs here
...
34 |     let mut new_test_var = test_var.make_clone(); // <= #3 This line also DOES NOT throw an error
   |                            -------- first borrow later used here

error[E0502]: cannot borrow `test_var` as immutable because it is also borrowed as mutable
  --> src\main.rs:39:5
   |
34 |     let mut new_test_var = test_var.make_clone(); // <= #3 This line also DOES NOT throw an error
   |                            -------- mutable borrow occurs here
...
39 |     test_var.repr();         // <= #4 This gives an error
   |     ^^^^^^^^ immutable borrow occurs here
40 |     another_test_var.repr();
41 |     new_test_var.repr();     // <= #5 This gives an error as well
   |     ------------ mutable borrow later used here

error[E0502]: cannot borrow `new_test_var` as immutable because it is also borrowed as mutable
  --> src\main.rs:41:5
   |
37 |     let mut last_test_var = new_test_var.make_clone();
   |                             ------------ mutable borrow occurs here
...
41 |     new_test_var.repr();     // <= #5 This gives an error as well
   |     ^^^^^^^^^^^^ immutable borrow occurs here
42 |     last_test_var.repr();
   |     ------------- mutable borrow later used here
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • *1st "copy" of test_var* has no references to `test_var`. – Shepmaster Nov 09 '20 at 21:33
  • That is true, however both structs try to borrow the exact same data, hence the <"> in "copy", since I am not actually copying or cloning it, but merely building a second structure with the exact same input. – David Fischermeier Nov 09 '20 at 21:38
  • [`#2` does not error](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9e74c71a804d9f8d42db4855d7d6ca7a) – Shepmaster Nov 09 '20 at 21:41
  • Your question might be answered by the answers of [What are non-lexical lifetimes?](https://stackoverflow.com/q/50251487/155423) (See [all the dupes of it](https://stackoverflow.com/questions/linked/50251487?lq=1) as well) . If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Nov 09 '20 at 21:41
  • [`#3` is part of this error](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=c460393192b09425a0c00f6e7b68b5f5) – Shepmaster Nov 09 '20 at 21:44
  • Sorry if my questions were not clear: So for once I am curious why borrowing a vector mutably (#2) behaves differently than borrowing a funtion mutably (#1). If I comment the whole vector part from the code, another_test_var can be built. Secondly why does making another struct (let another_test_var...) with the same variables as test_var, which does not compile, differ from test_var.make_clone(), which compiles (up to #4) even with the vector field present. – David Fischermeier Nov 09 '20 at 22:06
  • Apperantly the order matters and I think your link about the lexical lifetimes is spot-on. I think i misinterpreted the error messenges a bit as well as some lines only become errors, if something changes later on. Anyways thank you, if you don't have any more wisdom to share this can be closed I think. I was mainly surprised why some of this very forced code seemed to work despite it not being supposed to and maybe the compiler was just trying to hard to be my friend xD – David Fischermeier Nov 09 '20 at 22:20

0 Answers0