Does borrowing checker forbid the self-referential case?

⚓ rust    📅 2025-05-15    👤 surdeus    👁️ 4      

surdeus

Warning

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

An imaginary self-referential mode that would work in Rust might be

struct A<'a> {
    ptr: Option<&'a A<'a>>,
}
fn main() {
    let mut a = A { ptr: None };
    a.ptr = Some(&a);
}

However, this code is not compiled. The error is

error[E0506]: cannot assign to `a.ptr` because it is borrowed
 --> src/main.rs:6:5
  |
6 |     a.ptr = Some(&a);
  |     ^^^^^^^^^^^^^--^
  |     |            |
  |     |            `a.ptr` is borrowed here
  |     `a.ptr` is assigned to here but it was already borrowed
  |     borrow later used here

Does the borrowing checker forbid us from writing the self-referential structure in Rust?

NLL RFC seems to cover this case.

&a is borrowed for lifetime 'a, which keeps alive until a deads. According to the RFC: An assignment statement LV = RV is a shallow write to LV;

So, the relevant borrowings for a.ptr are determined by this rule:

For shallow accesses to the path lvalue, we consider borrows relevant if they meet one of the following criteria:

  • [...]
  • there is a loan for some prefix of the path lvalue;

So, &a is that relevant borrowing, which is the in-scope loan at LV = RV. The access to a.ptr is Write, and the relevant borrowing exists. They conflict with each other. So, the borrowing checker reports the error.

Is this the reason why we cannot write out self-referential structures in Rust?

Is this the mechanism of how the borrowing checker forbids us from creating a self-referential structure?

9 posts - 3 participants

Read full topic

🏷️ rust_feed