在Rust中,当我borrow 一个值时,编译器会注意到它,但当我替换它时,编译器不会注意到它,并发出E0597错误.

给定一个包含引用x的可变变量. 当我用对局部变量的引用替换其内容时,在局部变量之前 如果超出范围,我就把它换回原来的位置.

下面的代码显示了这一点:

struct X {payload : i32}

fn main() {
    let pl = X{payload : 44};
    {
        let mut x = &pl;
        {
            let inner = X{payload : 30};
            let tmp = std::mem::replace(&mut x, &inner);
            println! ("data ={:?}", x.payload);
            let _f = std::mem::replace(&mut x, &tmp);
        }
        println! ("data ={:?}", x.payload);
    }
}

错误是:

error[E0597]: `inner` does not live long enough
  --> src/main.rs:9:49
   |
9  |             let tmp = std::mem::replace(&mut x, &inner);
   |                                                 ^^^^^^ borrowed value does not live long enough
...
12 |         }
   |         - `inner` dropped here while still borrowed
13 |         println! ("data ={:?}", x.payload);
   |                                 --------- borrow later used here

For more information about this error, try `rustc --explain E0597`.

当我将引用inner赋给x时,编译器会注意到,但忽略了这样一个事实,即当inner仍然有效时,我再次将这个引用替换为对pl的原始引用.

预期输出应为:

data =30
data =44

我做错了什么?

推荐答案

我已经解决了这个问题.不幸的是,这是一个编译器错误或限制.

语义上等价的代码,代码的信用将属于发布了部分答案的人,但随后将其删除.

// This one will yields error E0597
struct X {payload : i32}

fn main() {
    let pl = X{payload : 44};
    {
        let mut x = &pl;
        println! ("data ={:?}", x.payload);
        {
            let inner = X{payload : 30};
            let tmp : &X = x;
            x = &inner;
            println! ("data ={:?}", x.payload);
            x = tmp;
        }
        println! ("data ={:?}", x.payload);
    }
}

此代码将产生相同的错误.

然而,一个小小的调整将使其编译时不会出现错误或警告.

// Compiles without errors/warnings.
struct X {payload : i32}

fn main() {
    let pl = X{payload : 44};
    {
        let mut x = &pl;
        println! ("data ={:?}", x.payload);
        {
            let inner = X{payload : 30};
            x = &inner;
            println! ("data ={:?}", x.payload);
            x = &pl;
        }
        println! ("data ={:?}", x.payload);
    }
}

这让我相信存在编译器错误.因为现在编译器发现inner的生存期与x的生存期是分离的.

唉.当您将内部块放入一个单独的函数中时,问题又回来了.所以这只是一个例子,Rust编译器有一些优化代码路径,它捕捉到了角落的情况.

// Yields error E0597 again.
struct X {payload : i32}

fn inner_func(x : &mut &X) {
    let inner = X{payload : 30};
    let tmp : &X = *x;
    *x = &inner;
    println! ("data ={:?}", (*x).payload);
    *x = &tmp;
}

fn main() {
    let pl = X{payload : 44};
    {
        let mut x : &X = &pl;
        inner_func(&mut &mut x);
        println! ("data ={:?}", x.payload);
    }
}

endless的生命周期 挤到inner的生命周期 以使其更大的方法获得了Frederico分,即使这意味着使用不安全的.

// This one compiles without errors/warnings.
struct X {payload : i32}

fn inner_func(x : &mut &X) {
    let inner = X{payload : 30};
    let tmp : &X = *x;
    unsafe {
        *x = std::mem::transmute::<_, &'static X>(&inner);
    }
    println! ("data ={:?}", (*x).payload);
    *x = &tmp;
}

fn main() {
    let pl = X{payload : 44};
    {
        let mut x : &X = &pl;
        inner_func(&mut &mut x);
        println! ("data ={:?}", x.payload);
    }
}

Rust相关问答推荐

当第二个`let`依赖于第一个`let()`时,如何在一行中有多个`let()`?

在不重写/专门化整个函数的情况下添加单个匹配手臂到特征的方法?

如何go 除铁 rust 中路径组件的第一项和最后一项?

使用铁 rust S还原对多个数组执行顺序kronecker积

用 rust 蚀中的future 展望 struct 的future

我应该将哪些文件放入我的GitHub存储库

在Rust中,Box:ed struct 与普通 struct 在删除顺序上有区别吗?

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

Rust面向对象设计模式

如何设置activx websocket actorless的消息大小限制?

Rust:为什么 &str 不使用 Into

为什么切片时需要参考?

返回迭代器考虑静态生命周期类型

如何基于常量在Rust中跳过一个测试

实现泛型的 Trait 方法中的文字

为什么允许重新分配 String 而不是 *&String

如何在 Rust 中编写修改 struct 的函数

为什么 no_std crate 可以依赖于使用 std 的 crate?

带有库+多个二进制文件的Cargo 项目,二进制文件由多个文件组成?

基于名称是否存在的条件编译