I am trying to use the newtype pattern to wrap a pre-existing type. That inner type has a modify
method which lets us work with a borrowed mutable value in a callback:
struct Val;
struct Inner(Val);
impl Inner {
fn modify<F>(&self, f: F)
where F: FnOnce(&mut Val) -> &mut Val { … }
}
Now I want to provide a very similar method on my newtype Outer
, which however should not work on Val
s but again a newtype wrapper 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(/* ??? */));
}
}
This code is a reduced example from the original API. I don't know why the reference is returned from the closure, maybe to facilitate chaining, but it shouldn't be necessary. It takes &self
because it uses internal mutability - it's a type representing a peripheral register on an embedded system
How do I get a &mut WrappedVal
from a &mut Val
?
I have tried various things, but all were busted by the borrow-checker. I cannot move the Val
out of the mutable reference to construct a proper WrappedVal
, and I couldn't get lifetimes to compile either when experimenting around with struct WrappedVal(&'? mut Val)
(which I don't really want actually, since they are complicating a trait implementation).
I eventually got it to compile (see Rust playground demo) using the absolute horror of
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()
});
but surely there must be a better way?