下面的代码(playgroung)适用于Miri,但是它没有未定义的行为吗?

use std::thread;

fn f1(x: &'static mut f64) {
    *x += 1.0;
}

fn f2(x: &'static mut f64) {
    *x *= *x;
}

fn f3(x: &'static mut f64) {
    *x = (*x).log10();
}

fn main() {
    let mut a = vec![1.0f64, 9.0, 100.0];
    let funcs = vec![f1, f2, f3];
    let a_mut = a.iter_mut().collect::<Vec<_>>();
    thread::scope(|s| {
        for (x,f) in a_mut.into_iter().zip(&funcs) {
            s.spawn(|| {
                f(unsafe{std::mem::transmute::<_,&'static mut f64>(x)});
            });
        }
    });
    println!("a -> {a:?}");
}

在此代码中,使用Transmute将非静态可变引用发送到将静态可变引用作为输入的函数.但是,执行被限制在可变引用的生存期内的范围内.


Fn(&'static mut f64) (playground)也有类似的问题

use std::thread;

fn f1(x: &'static mut f64) {
    *x += 1.0;
}

fn f2(x: &'static mut f64) {
    *x *= *x;
}

fn f3(x: &'static mut f64) {
    *x = (*x).log10();
}


fn main() {
    let mut a = vec![1.0f64, 9.0, 100.0];
    let funcs = vec![
        &f1 as &(dyn Fn(&'static mut f64) + Send + Sync),
        &f2 as &(dyn Fn(&'static mut f64) + Send + Sync),
        &f3 as &(dyn Fn(&'static mut f64) + Send + Sync)
    ];
    let a_mut = a.iter_mut().collect::<Vec<_>>();
    thread::scope(|s| {
        for (x,f) in a_mut.into_iter().zip(funcs) {
            s.spawn(|| {
                f(unsafe{std::mem::transmute::<_,&'static mut f64>(x)});
            });
        }
    });
    println!("a -> {a:?}");
}


注意:虽然我的问题是关于生命的改变,但这个例子有点人为,因为它可以在不改变的情况下重写,正如Chayim提到的,只需定义fn f1(x: &mut f64)fn f2(x: &mut f64)fn f3(x: & mut f64),而不是fn f1(x: &'static mut f64)fn f2(x: &'static mut f64)fn f3(x: &'static mut f64).

推荐答案

Lifetimes can never affect behavior.不幸的是,据我所知,官方没有记录这一点,但这是一般的概念.

如果您将这些引用交给未知代码,那么这将是unsound个,但假设所有代码都是已知的,并且在其生命周期之外实际上没有使用该引用,这是可以的.

Rust相关问答推荐

为什么我需要在这个代码示例中使用&

如何在Rust中实现Functor trait?

如何在Tauri中将变量从后端传递到前端

异步FN中的 rust 递归

防止cargo test 中的竞争条件

在跨平台应用程序中使用std::OS::Linux和std::OS::Windows

为什么TcpListener的文件描述符和生成的TcpStream不同?

如何在不调用Collect()的情况下为新型vec实现IntoIterator?

如果变量本身不是None,如何返回;如果没有,则返回None&Quot;?

Rust将String上的迭代器转换为&;[&;str]

Rust:为什么 &str 不使用 Into

为什么 js_sys Promise::new 需要 FnMut?

有什么方法可以通过使用生命周期来减轻嵌套生成器中的当生成器产生时borrow 可能仍在使用错误?

如何在 Emacs Elisp 中获得类似格式化的 LSP?

Rust/Serde/HTTP:序列化`Option`

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

Rust 异步和 AsRef 未被发送

如何在 Rust Polars 中可靠地连接 LazyFrames

如何存储返回 Future 的闭包列表并在 Rust 中的线程之间共享它?

有没有比多个 push_str() 调用更好的方法将字符串链接在一起?