a是一个Vec<i32>,可以在一个表达式中可变和不可变地引用:

fn main() {
    let mut a = vec![0, 1];
    a[0] += a[1]; // OK
}

我认为这是编译的,因为i32实现了Copy,所以我创建了另一个实现Copy的类型,并像第一个示例那样编译它,但它失败了:

use std::ops::AddAssign;

#[derive(Clone, Copy, PartialEq, Debug, Default)]
struct MyNum(i32);

impl AddAssign for MyNum {
    fn add_assign(&mut self, rhs: MyNum) {
        *self = MyNum(self.0 + rhs.0)
    }
}

fn main() {
    let mut b = vec![MyNum(0), MyNum(1)];
    b[0] += b[1];
}

playground

error[E0502]: cannot borrow `b` as immutable because it is also borrowed as mutable
  --> src/main.rs:14:13
   |
14 |     b[0] += b[1];
   |     --------^---
   |     |       |
   |     |       immutable borrow occurs here
   |     mutable borrow occurs here
   |     mutable borrow later used here
  1. 为什么我的MyNumi32的行为方式不同,尽管它实现了Copy
  2. 为什么向量可以在一个表达式中可变和不变地引用?

推荐答案

我相信你在这里看到的是,primitive types并不是真正意义上的std::ops.这std::ops条可能只是为了无缝的trait 扩展,等等.我认为Rust Tidbits: What Is a Lang Item?篇博文部分解释了这一点.

我导出了你的例子that works with primitive types的和平号.我得到:

    bb5: {
        StorageDead(_9);                 // bb5[0]: scope 1 at src/main.rs:6:8: 6:9
        _10 = CheckedAdd((*_8), move _5); // bb5[1]: scope 1 at src/main.rs:6:5: 6:17
        assert(!move (_10.1: bool), "attempt to add with overflow") -> [success: bb6, unwind: bb4]; // bb5[2]: scope 1 at src/main.rs:6:5: 6:17
    }

对于出错的代码,我很难导出MIR.在没有借阅判断的情况下输出MIR对我来说是一件 fresh 事,我不知道该怎么做.

Thisplayground 有一个非常相似的东西,但汇编:)

它给我打了一个add_assign的电话:

    bb3: {
        _8 = _9;                         // bb3[0]: scope 1 at src/main.rs:14:5: 14:9
        StorageDead(_10);                // bb3[1]: scope 1 at src/main.rs:14:8: 14:9
        StorageLive(_11);                // bb3[2]: scope 1 at src/main.rs:14:14: 14:22
        (_11.0: i32) = const 1i32;       // bb3[3]: scope 1 at src/main.rs:14:14: 14:22
                                         // ty::Const
                                         // + ty: i32
                                         // + val: Value(Scalar(0x00000001))
                                         // mir::Constant
                                         // + span: src/main.rs:14:20: 14:21
                                         // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) }
        _7 = const <MyNum as std::ops::AddAssign>::add_assign(move _8, move _11) -> [return: bb5, unwind: bb4]; // bb3[4]: scope 1 at src/main.rs:14:5: 14:22
                                         // ty::Const
                                         // + ty: for<'r> fn(&'r mut MyNum, MyNum) {<MyNum as std::ops::AddAssign>::add_assign}
                                         // + val: Value(Scalar(<ZST>))
                                         // mir::Constant
                                         // + span: src/main.rs:14:5: 14:22
                                         // + literal: Const { ty: for<'r> fn(&'r mut MyNum, MyNum) {<MyNum as std::ops::AddAssign>::add_assign}, val: Value(Scalar(<ZST>)) }
    }

原始 case 如何通过借阅判断器?因为不调用add_assign,所以可以在需要可变引用之前删除不可变引用.MIR只是在前面取消对所需位置的引用,并按值传递它.

    bb3: {
        _5 = (*_6);                      // bb3[0]: scope 1 at src/main.rs:6:13: 6:17
        StorageDead(_7);                 // bb3[1]: scope 1 at src/main.rs:6:16: 6:17
        ...
    }

Rust相关问答推荐

如何在rust中有条件地分配变量?

如何从polars DataFrame中获取一个列作为Option String?<>

泛型属性比较

在自身功能上实现类似移动的行为,以允许通过大小的所有者进行呼叫(&;mut;self)?

如何使用 list 在Rust for Windows中编译?

作为1字节位掩码的布尔值 struct

变量需要parse()中的显式类型

是否提供Bundle 在可执行文件中的warp中的静态文件?

对reqwest提供的这种嵌套JSON struct 进行反序列化

Windows 上 ndarray-linalg 与 mkl-stats 的链接时间错误

`tokio::pin` 如何改变变量的类型?

在给定 Rust 谓词的情况下,将 Some 转换为 None 的惯用方法是什么?

std::vector::shrink_to_fit 如何在 Rust 中工作?

在每个循环迭代中删除borrow

是否可以在 Rust 中的特定字符上实现特征?

如何在 Rust 中创建最后一个元素是可变长度数组的 struct ?

为什么这个闭包没有比 var 长寿?

有没有办法隐藏类型定义?

如何在不设置精度的情况下打印浮点数时保持尾随零?

返回 &str 但不是 String 时,borrow 时间比预期长