最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

borrow checker - Borrowing from dereference vs. Direct Borrowing in Rust - Stack Overflow

programmeradmin0浏览0评论

Env: rustc 1.82.0 (f6e511eec 2024-10-15)


Question: Dereferencing vs. Direct Borrowing in Rust

I’m confused about the difference between *&T and T in borrowing. The following code compiles with let b = &mut *a, but fails with let b = &mut x. Why does *a behave differently from x in this context?

Additionally, uncommenting the last line (*b = ...) causes the error:

cannot assign to *a because it is borrowed

fn annoying_borrow() {
    let mut x = Box::new(1);
    let a = &mut x;
    let b = &mut *a;
    // let b = &mut x; // error: cannot borrow `x` as mutable more than once at a time
    *a = Box::new(2);
    // *b = Box::new(3); // error: `*a` is assigned to here but it was already borrowed
}

Does using the *a instead of the x here further imply the subtle difference between them? Emmm, what I really want to explore is not the difference between *a and x, but the rules of borrowing in the Rust type system (compiler).


Background:

I’ve referenced Programming Rust, 2nd Ed. (Chapter 5), but I cannot fully comprehend this knowledge:

Shared access is read-only access.

Values borrowed by shared references are read-only. Across the lifetime of a shared reference, neither its referent, nor anything reachable from that referent, can be changed by anything. There exist no live mutable references to anything in that structure, its owner is held read-only, and so on. It’s really frozen.

Mutable access is exclusive access.

A value borrowed by a mutable reference is reachable exclusively via that reference. Across the lifetime of a mutable reference, there is no other usable path to its referent or to any value reachable from there. The only references whose lifetimes may overlap with a mutable reference are those you borrow from the mutable reference itself.

I wonder if there is any unified and detailed explanation of borrowing in Rust. Perhaps there used to be a clear set of rules about borrowing in Rust, but with the compiler continuously relaxing syntax restrictions (to facilitate coding in certain scenarios?), the current rules are more chaotic?

Env: rustc 1.82.0 (f6e511eec 2024-10-15)


Question: Dereferencing vs. Direct Borrowing in Rust

I’m confused about the difference between *&T and T in borrowing. The following code compiles with let b = &mut *a, but fails with let b = &mut x. Why does *a behave differently from x in this context?

Additionally, uncommenting the last line (*b = ...) causes the error:

cannot assign to *a because it is borrowed

fn annoying_borrow() {
    let mut x = Box::new(1);
    let a = &mut x;
    let b = &mut *a;
    // let b = &mut x; // error: cannot borrow `x` as mutable more than once at a time
    *a = Box::new(2);
    // *b = Box::new(3); // error: `*a` is assigned to here but it was already borrowed
}

Does using the *a instead of the x here further imply the subtle difference between them? Emmm, what I really want to explore is not the difference between *a and x, but the rules of borrowing in the Rust type system (compiler).


Background:

I’ve referenced Programming Rust, 2nd Ed. (Chapter 5), but I cannot fully comprehend this knowledge:

Shared access is read-only access.

Values borrowed by shared references are read-only. Across the lifetime of a shared reference, neither its referent, nor anything reachable from that referent, can be changed by anything. There exist no live mutable references to anything in that structure, its owner is held read-only, and so on. It’s really frozen.

Mutable access is exclusive access.

A value borrowed by a mutable reference is reachable exclusively via that reference. Across the lifetime of a mutable reference, there is no other usable path to its referent or to any value reachable from there. The only references whose lifetimes may overlap with a mutable reference are those you borrow from the mutable reference itself.

I wonder if there is any unified and detailed explanation of borrowing in Rust. Perhaps there used to be a clear set of rules about borrowing in Rust, but with the compiler continuously relaxing syntax restrictions (to facilitate coding in certain scenarios?), the current rules are more chaotic?

Share Improve this question edited Mar 6 at 13:38 galaxyzen asked Mar 6 at 11:06 galaxyzengalaxyzen 133 bronze badges 7
  • From the point of view of the borrow checker, let b = &mut *a is borrowing a, not x (which is still borrowed only by a). – Jmb Commented Mar 6 at 13:09
  • @cafce25 Sorry, I have deleted the redundant questions and only kept the first one. – galaxyzen Commented Mar 6 at 13:36
  • @Jmb There is some difference between rust and C language about the dereference *? I can't understand the "is borrowing a, not x", isn't *a and x essentially the same thing? – galaxyzen Commented Mar 6 at 13:42
  • C doesn't have a borrow checker. From the point of view of the generated code, *a and x are equivalent. From the point of view of the borrow checker &*a borrows from a, which is fine (but makes a temporarily inaccessible while the new borrow is in effect), whereas &x borrows from x, which results in multiple simultaneous borrows (since a is still in scope at that point and also borrows from x). – Jmb Commented Mar 6 at 14:40
  • @Jmb For me, this is really hard to understand. Is the a with the value that equals to the address of x in the stack frame? This view lingers in my mind:&*a => &(*a) => &x – galaxyzen Commented Mar 6 at 14:48
 |  Show 2 more comments

1 Answer 1

Reset to default 1

Mutable references can be 'inactive'. Only one mutable reference can be actively holding exclusive mutable access, but just because a reference exists, does not mean it holds access. When you borrow through a mutable reference, that access is transferred to the borrowing reference.

This means that you can create a mutable reference b through the mutable reference a that has access, transferring the access from a to b, until b is dropped when it is reverted to a. You can not use a directly whilst b exists, because it does not have access, like how x does not have access whilst a exists.

Additionally you can create a shared reference from a mutable reference, in which case, the mutable references access is downgraded to shared until the last reference borrowed from it is dropped.

发布评论

评论列表(0)

  1. 暂无评论