mem::forget(mem::uninitialized()) 是否定义了行为?
Is mem::forget(mem::uninitialized()) defined behavior?
在 mutagen 中,我正在注射各种
代码中的突变。我想改变的一件事是模式
if let Ok(x) = y { .. }
。然而,这构成了相当大的挑战,因为我
不知道 y
的类型——用户可以用一个
一元 Ok
变体。对于我们的情况,我仍然可以机会主义地改变它
实际上有一个 Result
其错误类型使用特征实现 Default
看起来像以下简化的:
#![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
}
}
}
唉,实现 Default
的错误并不多,所以这是
不太有用。即使 Result<T, Box<Error>>
的实现也会给出
我们更物有所值(并且完全有可能)。然而,鉴于我
不太关心代码实际上 检查 错误,我想知道我是否可以
通过将上述代码的突变扩展到
来做一个通用的实现
match Errorer::err(y, mutation) {
Ok(x) => { .. }
Err(x) => { mem::forget(x); }
}
并且有err
return Err(mem::uninitialized())
变异时——这也是
行为安全?注意:我从一个方法 returning Err(mem::uninitialized())
,
只是为了mem::forget
它以后。我看不出这会引起恐慌,所以我们应该
假设该值确实会被遗忘。
这是定义的行为还是我应该期待鼻恶魔?
不,这不是定义的行为,至少不是对所有类型。 (我不知道你的代码将如何作为突变的一部分被调用,所以我不知道你是否可以控制这里的类型,但是通用 impl
肯定会让你看起来像没有。)下面这段代码证明了这一点:
#![feature(never_type)]
use std::mem;
fn main() {
unsafe { mem::forget(mem::uninitialized::<!>()) }
}
如果您 run this on the playground,您将看到程序终止并发出 SIGILL。 ASM 输出显示 LLVM 刚刚优化了整个程序以立即发送 SIGILL,因为它使用无人居住类型 !
:
的值的方式
playground::main:
ud2
一般来说,在泛型代码中正确使用 mem::uninitialized
几乎是不可能的,参见例如this issue of rc::Weak
. For this reason, that function is in the process of being deprecated and replaced。但这对你没有帮助; Result<T, !>
.
你想做的是完全非法的
在 mutagen 中,我正在注射各种
代码中的突变。我想改变的一件事是模式
if let Ok(x) = y { .. }
。然而,这构成了相当大的挑战,因为我
不知道 y
的类型——用户可以用一个
一元 Ok
变体。对于我们的情况,我仍然可以机会主义地改变它
实际上有一个 Result
其错误类型使用特征实现 Default
看起来像以下简化的:
#![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
}
}
}
唉,实现 Default
的错误并不多,所以这是
不太有用。即使 Result<T, Box<Error>>
的实现也会给出
我们更物有所值(并且完全有可能)。然而,鉴于我
不太关心代码实际上 检查 错误,我想知道我是否可以
通过将上述代码的突变扩展到
match Errorer::err(y, mutation) {
Ok(x) => { .. }
Err(x) => { mem::forget(x); }
}
并且有err
return Err(mem::uninitialized())
变异时——这也是
行为安全?注意:我从一个方法 returning Err(mem::uninitialized())
,
只是为了mem::forget
它以后。我看不出这会引起恐慌,所以我们应该
假设该值确实会被遗忘。
这是定义的行为还是我应该期待鼻恶魔?
不,这不是定义的行为,至少不是对所有类型。 (我不知道你的代码将如何作为突变的一部分被调用,所以我不知道你是否可以控制这里的类型,但是通用 impl
肯定会让你看起来像没有。)下面这段代码证明了这一点:
#![feature(never_type)]
use std::mem;
fn main() {
unsafe { mem::forget(mem::uninitialized::<!>()) }
}
如果您 run this on the playground,您将看到程序终止并发出 SIGILL。 ASM 输出显示 LLVM 刚刚优化了整个程序以立即发送 SIGILL,因为它使用无人居住类型 !
:
playground::main:
ud2
一般来说,在泛型代码中正确使用 mem::uninitialized
几乎是不可能的,参见例如this issue of rc::Weak
. For this reason, that function is in the process of being deprecated and replaced。但这对你没有帮助; Result<T, !>
.