gpt4 book ai didi

reference - 如何将借来的值包装在也是借来的值的新类型中?

转载 作者:行者123 更新时间:2023-11-29 08:13:45 24 4
gpt4 key购买 nike

我正在尝试使用 newtype pattern包装一个预先存在的类型。该内部类型有一个 modify 方法,它让我们可以在回调中处理借用的可变值:

struct Val;

struct Inner(Val);

impl Inner {
fn modify<F>(&self, f: F)
where F: FnOnce(&mut Val) -> &mut Val { … }
}

现在我想在我的新类型 Outer 上提供一个非常相似的方法,但是它不应该在 Val 上工作,但又是一个新类型包装器 WrappedVal:

struct Outer(Inner);
struct WrappedVal(Val);

impl Outer {
fn modify<F>(&self, f: F)
where
F: FnOnce(&mut WrappedVal) -> &mut WrappedVal,
{
self.0.modify(|v| f(/* ??? */));
}
}

此代码是原始 API 的精简示例。我不知道为什么从闭包中返回引用,也许是为了方便链接,但这不是必需的。它采用 &self 因为它使用内部可变性 - 它是一种表示嵌入式系统上外围寄存器的类型

如何从 &mut Val 获取 &mut WrappedVal

我尝试过各种方法,但都被借用检查器破坏了。我无法将 Val 从可变引用中移出以构建适当的 WrappedVal,并且在尝试使用 struct WrappedVal( &'? mut Val)(我实际上并不想要,因为它们使特征实现复杂化)。

我最终得到它编译(见 Rust playground demo )使用绝对恐怖

self.0.modify(|v| unsafe {
(f((v as *mut Val as *mut WrappedVal).as_mut().unwrap()) as *mut WrappedVal as *mut Val)
.as_mut()
.unwrap()
});

但肯定有更好的方法吗?

最佳答案

您当前的定义没有安全的方法,并且不保证您的不安全代码是安全的。没有契约(Contract)规定 WrappedVal 的布局与 Val 的布局相匹配,即使仅此而已。

不使用unsafe的解决方案

不要这样做。相反,包装引用:

struct WrappedVal<'a>(&'a mut Val);

impl Outer {
fn modify<F>(&self, f: F)
where
F: FnOnce(WrappedVal) -> WrappedVal,
{
self.0.modify(|v| f(WrappedVal(v)).0)
}
}

使用unsafe的解决方案

您可以声明您的类型与其包装的类型具有相同的表示,通过repr(transparent) 使指针兼容:

#[repr(transparent)]
struct WrappedVal(given::Val);

impl Outer {
fn modify<F>(&self, f: F)
where
F: FnOnce(&mut WrappedVal) -> &mut WrappedVal,
{
self.0.modify(|v| {
// Insert documentation why **you** think this is safe
// instead of copy-pasting from Stack Overflow
let wv = unsafe { &mut *(v as *mut given::Val as *mut WrappedVal) };
let wv = f(wv);
unsafe { &mut *(wv as *mut WrappedVal as *mut given::Val) }
})
}
}

有了repr(transparent),两个指针就可以互换了。我跑了 a quick test with Miri and your full example并且没有收到任何错误,但这不是我没有搞砸其他事情的 Elixir 。

关于reference - 如何将借来的值包装在也是借来的值的新类型中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53999600/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com