为什么在Rust中直接将const引用转换为可变引用是无效的?

4

这段代码是正确的:

fn f() {
    let mut x = 11;
    b(&x as *const u8 as *mut u8);
}

fn b(x: *mut u8) {}

为什么(&x as *const u8 as *mut u8)是有效的,而(&x as *mut u8)是无效的?编译器报错如下:

error[E0606]: 将&u8转换为*mut u8是无效的

2个回答

8
"为什么?"的表面答案是这些只是Rust中as表达式的规则。引用自Nomicon

转换不具有传递性,也就是说,即使e as U1 as U2是有效的 表达式,e as U2未必是有效的。

使用as运算符,您可以执行显式强制转换类型转换
没有直接从&u8*mut u8的转换或强制转换。但是,存在从&T*const T的指针弱化强制转换和从大小类型的指针到任何其他类型的强制转换。这两种组合会导致您提出的问题中的表达式。
更深层次的问题是为什么设计语言方式。我实际上并不知道,因为在做出这些决策时我不在场,并且我在网络上找不到相关原理。Rust通常会尝试使用类型转换非常明确,以避免实际上未经意的转换,并保持规则简单。这些原则似乎也影响了这个特定的设计决策。

这就是我最终不得不做的事情,它很有道理,但一开始看起来很傻...让ptr:mut u8 =&op_create作为 const control_operation as * const u8 as * mut u8; - stu
1
@stu 如果你想节省一些打字时间,以及减少代码阅读时的无关噪音,你也可以使用&op_create as *const _ as *const _ as *mut u8 - Sven Marnach
有趣的是,它不关心你强制转换或转型的类型,只要你将其转换为const vs mut。谢谢。 - stu
下划线告诉编译器要推断类型。每个下划线只有一种有效的类型,因此我们不需要明确指定它。 - Sven Marnach

0

因为 Rust 引用是常量。

你想要做的是将可变引用 &mut x 转换为一个原始整数可变指针 *mut i32

这段代码是有效的:

let mut x = 42;
let ptr = &mut x as *mut _;
// equivalent to
let ptr_2 = &x as *const _ as *mut _;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接