Rust mem::forget(mem::uninitialized())是否定义了行为?

Rust mem::forget(mem::uninitialized())是否定义了行为?,rust,undefined-behavior,unsafe,Rust,Undefined Behavior,Unsafe,在,我正在注射各种药物 代码中的突变。我想改变的一件事是模式 如果让Ok(x)=y{..}。然而,正如我所说,这带来了相当大的挑战 无法知道y的类型–用户可能已使用 一元Okvariant。我仍然可以在我们 实际上有一个结果,其错误类型使用特征实现默认值 看起来如下所示: #![feature(specialization)] pub trait Errorer { fn err(self, mutate: bool) -> Self; } impl<X> Erro

在,我正在注射各种药物 代码中的突变。我想改变的一件事是模式
如果让Ok(x)=y{..}
。然而,正如我所说,这带来了相当大的挑战 无法知道
y
的类型–用户可能已使用 一元
Ok
variant。我仍然可以在我们 实际上有一个
结果
,其错误类型使用特征实现
默认值
看起来如下所示:

#![feature(specialization)]

pub trait Errorer {
    fn err(self, mutate: bool) -> Self;
}

impl<X> Errorer for X {
    default fn err(self, _mutate: bool) -> Self {
        self
    }
}

impl<T, E> Errorer for Result<T, E>
where
    E: Default,
{
    fn err(self, mutate: bool) -> Self {
        if mutate {
            Err(Default::default())
        } else {
            self
        }
    }
}
并且在变异时让
err
返回
err(mem::uninitialized())
——这也是如此 行为安全?注意:我从一个方法返回
Err(mem::uninitialized())
, 只想
mem::以后忘记它。我看这不会引起恐慌,所以我们应该
假设该值确实会被遗忘


这是定义的行为还是我应该期待鼻魔?

不,这不是定义的行为,至少不是所有类型的行为。(我不知道作为变异的一部分,您的代码将如何被调用,因此我不知道您是否可以控制这里的类型,但是泛型
impl
确保看起来您没有这样做。)下面的代码片段演示了这一点:

#![feature(never_type)]
use std::mem;

fn main() {
    unsafe { mem::forget(mem::uninitialized::<!>()) }
}

一般来说,在泛型代码中几乎不可能正确使用
mem::uninitialized
,请参见示例。由于这个原因,这个功能正在被实现。但这对你没有帮助;您想做的事情对于
结果

来说完全是非法的,这是我想到的:Rust可以根据其变体的有效负载的表示自由地操纵它如何表示枚举(即使
选项
大小相同的技巧)。我不知道有任何布局优化会影响
结果
,但我也看不出有任何理由不能在将来添加它们。如果是这种情况,
mem::uninitialized
可能会使
E
值处于无效状态,从而改变
结果的解释方式。是的,我也这么认为。因此,在将无效状态放入枚举时,无法保证定义的行为。目前还不确定是否是这样,但
结果
可以而且(将来某一天)应该具有与
T
相同的布局。LLVM只是将整个程序优化为立即SIGILL-这就是高效的代码生成。
#![feature(never_type)]
use std::mem;

fn main() {
    unsafe { mem::forget(mem::uninitialized::<!>()) }
}
playground::main:
    ud2