“Does &mut T implements Borrow break a mutable reference rule?”

huangapple go评论60阅读模式
英文:

Does &mut T implements Borrow<T> break a mutable reference rule?

问题

&mut T 实现了 Borrow<T>,所以 (&mut T).borrow() 会创建 &T。这是否违反了“如果我们有一个可变引用,就不能有任何其他引用(可变或不可变)”的规则?

use std::borrow::Borrow;
let mut n = 1;
let r1: &mut i32 = &mut n;
let r2: &i32 = r1.borrow();

println!("log: {r1} {r2}");

这段代码可以编译,但如果我将 r1.borrow() 改为 &n,它将报错。

引用系统的确切规则是什么?

Playground

英文:

&amp;mut T implements Borrow&lt;T&gt;,so (&amp;mut T).borrow() will create &amp;T. Does this break the rule that “if we have one mutable reference, we can not have any other references (mutable or not)”?

use std::borrow::Borrow;
let mut n = 1;
let r1: &amp;mut i32 = &amp;mut n;
let r2: &amp;i32 = r1.borrow();

println!(&quot;log: {r1} {r2}&quot;);

The code compiles, but if I change r1.borrow() to &amp;n, it will report error

What's the exact rule of the reference system?

Playground

答案1

得分: 1

以下是代码部分的翻译:

let r1: &mut i32 = &mut n;
let r2: &i32 = &*r1;
let r3: &i32 = &*r1;
fn takes_ref_mut_ref(_: &&mut i32) {}
takes_ref_mut_ref(&r1);
let r4 = *r1;
fn print_three(a: &i32, b: &i32, c: &i32) {
    println!("{a} {b} {c}")
}
print_three(r1, r2, r3);
fn takes_ref_ref(_: &&i32) {}
takes_ref_ref(&r1);
fn print_three_mut(a: &mut i32, b: &i32, c: &i32) {
    println!("{a} {b} {c}")
}
print_three_mut(r1, r2, r3);
*r1 = 5;
英文:

This is more general than Borrow. You can do the same thing with regular references:

let r1: &amp;mut i32 = &amp;mut n;
let r2: &amp;i32 = &amp;*r1;

When you think about it, it's very necessary to be able to make immutable references from mutable references. For example, you need it to call &amp;self methods on &amp;mut variables.

But rust still ensures you aren't using the mut property of the variable.

Things you can do:

  • Give out more &amp; references
let r3: &amp;i32 = &amp;*r1;
  • Use it behind another &amp; reference
fn takes_ref_mut_ref(_: &amp;&amp;mut i32) {}
takes_ref_mut_ref(&amp;r1);
  • Copy types that implement Copy
let r4 = *r1;
  • Deref to &amp; (this does &amp;*r1 implicitly)
fn print_three(a: &amp;i32, b: &amp;i32, c: &amp;i32) {
    println!(&quot;{a} {b} {c}&quot;)
}
print_three(r1, r2, r3);

Things you can't do:

  • Implicitly use it as a &amp;&amp;
fn takes_ref_ref(_: &amp;&amp;i32) {}
takes_ref_ref(&amp;r1);
  • Use it as &amp;mut directly
fn print_three_mut(a: &amp;mut i32, b: &amp;i32, c: &amp;i32) {
    println!(&quot;{a} {b} {c}&quot;)
}
print_three_mut(r1, r2, r3);
  • And obviously, mutate the variable
*r1 = 5;

(playground)

huangapple
  • 本文由 发表于 2023年3月4日 00:10:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/75629427.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定