Is it possible to create a wrapper around an &mut that acts like an &mut - rust

The following code fails to compile because MutRef is not Copy. It can not be made copy because &'a mut i32 is not Copy. Is there any way give MutRef similar semantics to &'a mut i32?
The motivation for this is being able to package up a large set of function parameters into a struct so that they can be passed as a group instead of needing to be passed individually.
struct MutRef<'a> {
v: &'a mut i32
}
fn wrapper_use(s: MutRef) {
}
fn raw_use(s: &mut i32) {
}
fn raw_ref() {
let mut s: i32 = 9;
let q = &mut s;
raw_use(q);
raw_use(q);
}
fn wrapper() {
let mut s: i32 = 9;
let q = MutRef{ v: &mut s };
wrapper_use(q);
wrapper_use(q);
}

No.
The name for this feature is "implicit reborrowing" and it happens when you pass a &mut reference where the compiler expects a &mut reference of a possibly different lifetime. The compiler only implicitly reborrows when the actual type and the expected type are both &mut references. It does not work with generic arguments or structs that contain &mut references. There is no way in current Rust to make a custom type that can be implicitly reborrowed. There is an open issue about this limitation dating from 2015, but so far nobody has proposed any way to lift it.
You can always implement your own method to explicitly reborrow:
impl<'a> MutRef<'a> {
// equivalent to fn reborrow(&mut self) -> MutRef<'_>
fn reborrow<'b>(&'b mut self) -> MutRef<'b> {
MutRef {v: self.v}
}
}
fn wrapper() {
let mut s: i32 = 9;
let mut q = MutRef{ v: &mut s };
wrapper_use(q.reborrow()); // does not move q
wrapper_use(q); // moves q
}
See also
Why is the mutable reference not moved here?
Type inference and borrowing vs ownership transfer

Related

Extract code into dedicated function (Rust) (lifetime related)

(copied from my reddit question), hoping to get more answers)
I'm currently having a pretty hard time trying to make the following code work. I'm simply trying to extract a specific code block into it's own function, but I'm having a hard time due to the lifetimes related to it. I know very well there's a solution to this since it compiles with no problem when it is in it's own monolithic function, but the moment I try to start separating it, borrowck gets very angry.
trait Item<'s: 'i, 'i>: Sized + 'i {
type Slice: 's;
fn get<'a: 'i>(slice: &'a mut Self::Slice) -> Self where 's: 'a;
}
impl<'s: 'i, 'i> Item<'s, 'i> for &'i mut u32 {
type Slice = &'s mut [u32];
fn get<'a: 'i>(slice: &'a mut Self::Slice) -> Self where 's: 'a {
&mut slice[0]
}
}
// This don't work (even tried messing with HRTBs but still not able to make it compile properly)
/*
fn extracted<'a: 'i, 's: 'i, 'i, I: Item<'s, 'i>>(slice: &'a mut I::Slice) {
for x in 0..4 {
let func = I::get(slice);
}
}
*/
fn main() {
let mut array = [0, 0, 0, 0u32];
let mut slice = array.as_mut_slice();
let mutable = &mut slice;
for x in 0..10 {
let value = <&mut u32>::get(mutable);
}
}
I tested out the suggestions from the Reddit answers, although it does not seems that the Copy trait has anything to do with it.
Link to playground

lifetime / borrow of nested structs error [duplicate]

This question already has an answer here:
How can I create my own data structure with an iterator that returns mutable references?
(1 answer)
Closed 6 months ago.
I'm having a lifetime issue when implementing an iterator on custom struct containing borrows of vecs.
I've been trying different solutions but can't fix it by myself (I'm still a beginner) and I want to understand what is going on.
here is a playground example of my issue, that should be simple enough.
This is the example :
struct SomeData;
struct CustomIterator<'a> {
pub vec: &'a mut Vec<SomeData>,
pub index: usize,
}
struct MultipleIterator<'a> {
iter1: CustomIterator<'a>,
iter2: CustomIterator<'a>,
}
impl<'a> Iterator for MultipleIterator<'a> {
type Item = (&'a mut SomeData, &'a mut SomeData);
fn next(&mut self) -> Option<Self::Item> {
Some((
match self.iter1.vec.get_mut(self.iter1.index) {
Some(mut data) => &mut data,
None => return None,
},
match self.iter2.vec.get_mut(self.iter2.index) {
Some(mut data) => &mut data,
None => return None,
}
))
}
}
I don't unerstand why I can't borrow out of the next function, since I am borrowing the struct anyway when calling next()
This is actually quite tricky to implement safely and requires a lot of care to do correctly.
First things first though:
match self.iter1.vec.get_mut(self.iter1.index) {
Some(mut data) => &mut data,
None => return None,
},
This is a problem because Vec::get_mut already returns a Option<&mut T>. So in the Some(mut data) arm, data already is a mutable reference. When you try to return &mut data, you're trying to return a &mut &mut T which doesn't work. Instead, just do this:
match self.iter1.vec.get_mut(self.iter1.index) {
Some(data) => data,
None => return None,
},
We can tidy this up even more with the ? operator which does the same thing. I'm gonna substitute SomeData for i32 from now on to demonstrate something later.
impl<'a> Iterator for MultipleIterator<'a> {
type Item = (&'a mut i32, &'a mut i32);
fn next(&mut self) -> Option<Self::Item> {
Some((
self.iter1.vec.get_mut(self.iter1.index)?,
self.iter2.vec.get_mut(self.iter2.index)?,
))
}
}
This still doesn't work and now we're getting to the core of the problem. The signature of next is
fn next(&mut self) -> Option<(&'a mut i32, &'a mut i32)>
which can be desugared to
fn next<'b>(&'b mut self) -> Option<(&'a mut i32, &'a mut i32)>
This means that the lifetime of &mut self ('b) is completely decoupled from the lifetime of the references we return ('a). Which makes total sense. If that wasn't the case, we couldn't do
let mut v = vec![1,2,3];
let mut iter = v.iter_mut();
let next1: &mut i32 = iter.next().unwrap();
let next2: &mut i32 = iter.next().unwrap();
because the lifetime of next1 would have to be the same lifetime of iter, i.e. that of v. But you can't have multiple mutable references to v at the same time, so next2 would be illegal.
So you're getting an error because Rust only knows that self is borrowed for 'b but you're telling it that you're returning a reference with lifetime 'a which it can't verify to be true.
And for good reason, because as it stands right now, your implementation isn't safe! Let's just throw caution to the wind and tell Rust that this is okay with unsafe:
impl<'a> Iterator for MultipleIterator<'a> {
type Item = (&'a mut i32, &'a mut i32);
fn next(&mut self) -> Option<Self::Item> {
unsafe {
Some((
&mut *(self.iter1.vec.get_mut(self.iter1.index)? as *mut _),
&mut *(self.iter2.vec.get_mut(self.iter2.index)? as *mut _),
))
}
}
}
It's not important what exactly this does, it basically just tells the compiler to shut up and trust me.
But now, we can do this:
let mut v1 = vec![1, 2, 3];
let mut v2 = vec![4, 5, 6];
let mut mi = MultipleIterator {
iter1: CustomIterator {
vec: &mut v1,
index: 0,
},
iter2: CustomIterator {
vec: &mut v2,
index: 0,
},
};
let next1 = mi.next().unwrap();
let next2 = mi.next().unwrap();
assert_eq!(next1, (&mut 1, &mut 4));
assert_eq!(next2, (&mut 1, &mut 4));
*next1.0 += 1;
assert_eq!(next1, (&mut 2, &mut 4));
assert_eq!(next2, (&mut 2, &mut 4));
We have broken Rust's most important rule: never have two mutable references to the same thing at once.
This can only be safe if your Iterator implementation can never return a mutable reference to something more than once. You could increment index each time, for example (although this still requires unsafe):
impl<'a> Iterator for MultipleIterator<'a> {
type Item = (&'a mut i32, &'a mut i32);
fn next(&mut self) -> Option<Self::Item> {
let next1 = self.iter1.vec.get_mut(self.iter1.index)?;
let next2 = self.iter2.vec.get_mut(self.iter2.index)?;
self.iter1.index += 1;
self.iter2.index += 1;
// SAFETY: this is safe because we will never return a reference
// to the same index more than once
unsafe { Some((&mut *(next1 as *mut _), &mut *(next2 as *mut _))) }
}
}
Here is an interesting related read from the nomicon; the "mutable slice" example being particularly relevant to your problem.

Why Rust can't coerce mutable reference to immutable reference in a type constructor?

It is possible to coerce &mut T into &T but it doesn't work if the type mismatch happens within a type constructor.
playground
use ndarray::*; // 0.13.0
fn print(a: &ArrayView1<i32>) {
println!("{:?}", a);
}
pub fn test() {
let mut x = array![1i32, 2, 3];
print(&x.view_mut());
}
For the above code I get following error:
|
9 | print(&x.view_mut());
| ^^^^^^^^^^^^^ types differ in mutability
|
= note: expected reference `&ndarray::ArrayBase<ndarray::ViewRepr<&i32>, ndarray::dimension::dim::Dim<[usize; 1]>>`
found reference `&ndarray::ArrayBase<ndarray::ViewRepr<&mut i32>, ndarray::dimension::dim::Dim<[usize; 1]>>`
It is safe to coerce &mut i32 to &i32 so why it is not applied in this situation? Could you provide some examples on how could it possibly backfire?
In general, it's not safe to coerce Type<&mut T> into Type<&T>.
For example, consider this wrapper type, which is implemented without any unsafe code and is therefore sound:
#[derive(Copy, Clone)]
struct Wrapper<T>(T);
impl<T: Deref> Deref for Wrapper<T> {
type Target = T::Target;
fn deref(&self) -> &T::Target { &self.0 }
}
impl<T: DerefMut> DerefMut for Wrapper<T> {
fn deref_mut(&mut self) -> &mut T::Target { &mut self.0 }
}
This type has the property that &Wrapper<&T> automatically dereferences to &T, and &mut Wrapper<&mut T> automatically dereferences to &mut T. In addition, Wrapper<T> is copyable if T is.
Assume that there exists a function that can take a &Wrapper<&mut T> and coerce it into a &Wrapper<&T>:
fn downgrade_wrapper_ref<'a, 'b, T: ?Sized>(w: &'a Wrapper<&'b mut T>) -> &'a Wrapper<&'b T> {
unsafe {
// the internals of this function is not important
}
}
By using this function, it is possible to get a mutable and immutable reference to the same value at the same time:
fn main() {
let mut value: i32 = 0;
let mut x: Wrapper<&mut i32> = Wrapper(&mut value);
let x_ref: &Wrapper<&mut i32> = &x;
let y_ref: &Wrapper<&i32> = downgrade_wrapper_ref(x_ref);
let y: Wrapper<&i32> = *y_ref;
let a: &mut i32 = &mut *x;
let b: &i32 = &*y;
// these two lines will print the same addresses
// meaning the references point to the same value!
println!("a = {:p}", a as &mut i32); // "a = 0x7ffe56ca6ba4"
println!("b = {:p}", b as &i32); // "b = 0x7ffe56ca6ba4"
}
Full playground example
This is not allowed in Rust, leads to undefined behavior and means that the function downgrade_wrapper_ref is unsound in this case. There may be other specific cases where you, as the programmer, can guarantee that this won't happen, but it still requires you to implement it specifically for those case, using unsafe code, to ensure that you take the responsibility of making those guarantees.
Consider this check for an empty string that relies on content staying unchanged for the runtime of the is_empty function (for illustration purposes only, don't use this in production code):
struct Container<T> {
content: T
}
impl<T> Container<T> {
fn new(content: T) -> Self
{
Self { content }
}
}
impl<'a> Container<&'a String> {
fn is_empty(&self, s: &str) -> bool
{
let str = format!("{}{}", self.content, s);
&str == s
}
}
fn main() {
let mut foo : String = "foo".to_owned();
let container : Container<&mut String> = Container::new(&mut foo);
std::thread::spawn(|| {
container.content.replace_range(1..2, "");
});
println!("an empty str is actually empty: {}", container.is_empty(""))
}
(Playground)
This code does not compile since &mut String does not coerce into &String. If it did, however, it would be possible that the newly created thread changed the content after the format! call but before the equal comparison in the is_empty function, thereby invalidating the assumption that the container's content was immutable, which is required for the empty check.
It seems type coercions don't apply to array elements when array is the function parameter type.
playground

borrowed value does not live long enough in this case ( Vec<&Fn(i32) -> i32> )

I am having this error, other times I had something similar and I have been able to solve, in different ways but now is not how to solve in this case:
borrowed value does not live long enough in
I moved the code that fails one more simple, but I can not find the error:
fn main(){
let mut v: Vec<&Fn(i32) -> i32> = Vec::new();
v.push(&ops_code1);
//v.push(&ops_code2);
//v.push(&ops_code3);
}
fn ops_code1(value: i32) -> i32 {
..//
error: borrowed value does not live long enough
v.push(&ops_code1);
play.rust
What you are doing here is creating a Vec of closures. In Rust static functions are treated slightly differently from closures, so when we create the reference a closure is actually created. If we do that after creating the Vec the resulting closure gets a shorter lifetime than the Vec, which is an error. We can instead use a let to create the closure before the Vec, giving a long enough lifetime, outliving the Vec:
fn main() {
let extended = &ops_code1;
let mut v: Vec<&Fn(i32) -> i32> = Vec::new();
// Note that placing it here does not work:
// let extended = &ops_code1;
v.push(extended);
//v.push(&ops_code2);
//v.push(&ops_code3);
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
Rust Playground
However, if you only use static functions - and not closures - the following also works fine, and lets you avoid the extra let:
fn main() {
let mut v: Vec<fn(i32) -> i32> = Vec::new();
v.push(ops_code1);
v.push(ops_code2);
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
fn ops_code2(value: i32) -> i32 {
println!("ops_code2 {}", value);
value
}
Rust Playground
A third option is to use boxed closures, which let's you use both closures and static functions without the extra lets, but with its own trade-offs:
fn main() {
let mut v: Vec<Box<Fn(i32) -> i32>> = Vec::new();
v.push(Box::new(ops_code1));
v.push(Box::new(ops_code2));
for f in v {
f(1);
}
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
fn ops_code2(value: i32) -> i32 {
println!("ops_code2 {}", value);
value
}
Rust Playground

Getting value from a collection without using the Clone trait

Is it possible to get a value from a collection and apply a method to it which accepts only self and not &self?
Minimal Working Example
What I would like to write is something akin to:
use std::collections::HashMap;
fn get<B>(key: i32, h: HashMap<i32, Vec<(i32, B)>>) -> i32 where B: Into<i32> {
let v: &Vec<(i32, B)> = h.get(&key).unwrap();
let val: &B = v.first().unwrap().1;
// Do something to be able to call into
// I only need the value as read-only
// Does B have to implement the Clone trait?
return val.into();
}
I have tried in vain to dribble mut here and there to try to appease compiler error after compiler error, but this is really a fool's errand.
use std::collections::HashMap;
fn get<B>(key: i32, mut h: HashMap<i32, Vec<(i32, B)>>) -> i32 where B: Into<i32> {
let mut v: &Vec<(i32, B)> = h.get_mut(&key).unwrap();
let ref mut val: B = v.first_mut().unwrap().1;
return (*val).into();
}
Is this sort of thing even possible or does B have to implement the Clone trait?
I've also tried:
Unsafe
Raw pointers
I've not tried:
Box
Other Rust constructs that I have not encountered,
I mention this to explicitly state that I have not
omitted any approaches that I know of.
Is it possible to get a value from a collection and apply a method to it which accepts only self and not &self?
In general, no, not without removing it from the collection. The collection owns the value. Methods that take self want to transform the item while consuming the ownership, so you have to transfer ownership.
Cloning or copying an item creates a new item with new ownership that you can then give to the method.
In your particular case, you can almost get away with this exciting where clause:
where for<'a> &'a B: Into<i32>
Except From<&i32> is not implemented for i32. You can write a trait that does what you want though:
use std::collections::HashMap;
trait RefInto<T> {
fn into(&self) -> T;
}
impl RefInto<i32> for i32 {
fn into(&self) -> i32 { *self }
}
fn get<B>(key: i32, h: HashMap<i32, Vec<(i32, B)>>) -> i32
where B: RefInto<i32>
{
let v = h.get(&key).unwrap();
let val = &v.first().unwrap().1;
val.into()
}
// ----
fn main() {
let mut map = HashMap::new();
map.insert(42, vec![(100, 200)]);
let v = get(42, map);
println!("{:?}", v);
}
Alternatively, you might be able to make use of Borrow:
use std::collections::HashMap;
use std::borrow::Borrow;
fn get<B>(key: i32, h: HashMap<i32, Vec<(i32, B)>>) -> i32
where B: Borrow<i32>
{
let v = h.get(&key).unwrap();
let val = &v.first().unwrap().1;
*val.borrow()
}
The function consumes the HashMap. I'm assuming this is your intent and that you therefore don't care about any of its content except the one element you wish to convert into an i32.
You can use the HashMap::remove method to extract a value. You can then use Vec::swap_remove to extract the first element.
use std::collections::HashMap;
fn get<B>(key: i32, mut h: HashMap<i32, Vec<(i32, B)>>) -> i32 where B: Into<i32> {
h.remove(&key)
.unwrap()
.swap_remove(0)
.1
.into()
}
If B is cheap to copy, then it makes more sense to write a function where it is copied.
The above doesn't handle errors. A version with error handling could look like this:
use std::collections::HashMap;
fn get<B>(key: i32, mut h: HashMap<i32, Vec<(i32, B)>>) -> Option<i32> where B: Into<i32> {
h.remove(&key)
.and_then(|mut vec| {
if vec.is_empty() { None }
else { Some(vec.swap_remove(0).1.into()) }
})
}
Vec::swap_remove isn't ideal. The functionality of moving an element at an arbitrary index out of the vector without any other work would be handled by the IndexMove trait which doesn't yet exist though.

Resources