【发布时间】:2019-01-01 22:59:56
【问题描述】:
我正在尝试使用newtype pattern 来包装预先存在的类型。该内部类型有一个modify 方法,它允许我们在回调中使用借用的可变值:
struct Val;
struct Inner(Val);
impl Inner {
fn modify<F>(&self, f: F)
where F: FnOnce(&mut Val) -> &mut Val { … }
}
现在我想在我的新类型Outer 上提供一个非常相似的方法,但是它不应该在Vals 上工作,但又是一个新类型包装器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()
});
但肯定有更好的方法吗?
【问题讨论】:
标签: reference rust borrowing newtype