Let's try to compile this code:
use std::cell::RefCell;
struct Foo {
v: Vec<RefCell<u8>>,
}
impl Foo {
fn f(&self, i: usize) {
let t = &mut *self.v[i].borrow_mut();
//let t = &mut *{self.v[i].borrow_mut()}; //compiled ok
}
}
fn main() {}
Compilation error:
error[E0596]: cannot borrow field `self.v` of immutable binding as mutable
--> src/main.rs:9:23
|
8 | fn f(&self, i: usize) {
| ----- use `&mut self` here to make mutable
9 | let t = &mut *self.v[i].borrow_mut();
| ^^^^^^ cannot mutably borrow field of immutable binding
Why does this code require adding &mut self to function signature in order to compile?
This is a known issue where IndexMut is sometimes selected when Index should actually be used.
Your workaround of using {} is reasonable, but you can also use Index explicitly:
use std::cell::RefCell;
fn f(v: Vec<RefCell<u8>>) {
use std::ops::Index;
let _t = &mut v.index(0).borrow_mut();
}
fn main() {}
See also:
Why does a mutable borrow of a closure through DerefMut not work?
How to use `BorrowMut` contained within `RefCell`?
Another workaround is to explicitly call RefCell::borrow_mut(&v[0]).
Related
Consider the following code:
struct Foo<'a> {
borrowed: &'a u8,
owned_one: Vec<u8>,
owned_two: Vec<u8>,
output: usize
}
impl<'a> Foo<'a> {
fn do_stuff(&mut self) {
self.output = self.owned_one.len();
let zipped = self.owned_one.iter().zip(self.owned_two.iter());
Self::subroutine(&zipped);
}
fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}
fn main() {
let num = 0u8;
let mut foo = Foo {
borrowed: &num,
owned_one: vec![0],
owned_two: vec![1],
output: 0
};
foo.do_stuff();
let _out = &foo.output;
}
(playground link)
It doesn't compile, producing the following error:
error: lifetime may not live long enough
--> src/lib.rs:12:9
|
8 | impl<'a> Foo<'a> {
| -- lifetime `'a` defined here
9 | fn do_stuff(&mut self) {
| - let's call the lifetime of this reference `'1`
...
12 | Self::subroutine(&zipped);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a`
I don't fully understand the complaint - surely self would always have the lifetime assigned to the class we're implementing? - but I can understand that both arguments to zip() need to last the same time. So I change do_stuff to take &'a mut self.
struct Foo<'a> {
borrowed: &'a u8,
owned_one: Vec<u8>,
owned_two: Vec<u8>,
output: usize
}
impl<'a> Foo<'a> {
fn do_stuff(&'a mut self) {
self.output = self.owned_one.len();
let zipped = self.owned_one.iter().zip(self.owned_two.iter());
Self::subroutine(&zipped);
}
fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}
}
fn main() {
let num = 0u8;
let mut foo = Foo {
borrowed: &num,
owned_one: vec![0],
owned_two: vec![1],
output: 0
};
foo.do_stuff();
let _out = &foo.output;
}
However, now compilation fails with:
error[E0502]: cannot borrow `foo.output` as immutable because it is also borrowed as mutable
--> src/lib.rs:27:16
|
26 | foo.do_stuff();
| -------------- mutable borrow occurs here
27 | let _out = &foo.output;
| ^^^^^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
Why has specifying a lifetime for self in the argument list for do_stuff meant that I suddenly can't take the immutable reference to foo later; and what can I do about it?
writing fn do_stuff(&'a mut self) in this context mean that the lifetime of this borrow of self, must life as long as what this self has borrow borrowed. That very often not what you want.
Your mistake is here fn subroutine<Arg: Iterator<Item=(&'a u8, &'a u8)>>(_zipped: &Arg) {}. Think of lexical meaning of your declaration. Your method return nothing but require a "parent" lifetime ? There is no reason to. The simple solution is simply to introduce a new lifetime for your Item. Like fn subroutine<'i, Arg: Iterator<Item=(&'i u8, &'i u8)>>(_zipped: &Arg) {}. Unless your function return something link to 'a, no lifetime of parent should be here.
Also, it's better to accept IntoIterator it's more generic, and there is no reason to take it by reference and finally when you have such complex generic better use where, and really really if you want to be pedantic you need two lifetime:
fn subroutine<'i, 'j, Arg>(_zipped: Arg)
where
Arg: IntoIterator<Item = (&'i u8, &'j u8)>,
{
}
So, I have the following problem. I have a structure implementation, and one of the methods of this structure consumes the instance of the structure, which is ok by me, as it is literally the last thing I want to do in my program with this instance (my_struct), but it's totally not OK with the borrow checker:
use std::thread;
struct MyStruct {
some_field: Vec<String>
}
impl MyStruct {
fn new() -> Self {
MyStruct {
some_field: vec!("str".to_string())
}
}
fn do_something_with_self_in_thread(&'static mut self) {
thread::spawn(move || self.some_field = vec!("another_str".to_string()));
}
}
fn main() {
let my_struct: &'static mut MyStruct = &mut MyStruct::new();
my_struct.do_something_with_self_in_thread()
// Some blocking call will follow
}
Error:
error[E0716]: temporary value dropped while borrowed
--> src/main.rs:20:49
|
20 | let my_struct: &'static mut MyStruct = &mut MyStruct::new();
| --------------------- ^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
| |
| type annotation requires that borrow lasts for `'static`
21 | my_struct.do_something_with_self_in_thread()
22 | }
| - temporary value is freed at the end of this statement
For more information about this error, try `rustc --explain E0716`.
I tried playing around with lifetimes, but resultless.
How do I get myself out of this situation?
Playground link
When we say a method consumes the instance, then it should take self and not a mutable borrow &mut self in the definition.
i.e.
impl MyStruct {
...
fn do_something_with_self_in_thread(self) {
...
}
}
As commenters have already said, your second problem is with lifetimes. The compiler can't reason about references not outliving owners of resources if they are in separate threads. So to this end the thread::spawn method has trait bounds requiring that the closure is 'static, which means the variables it captures can live as long as they like. Examples which are valid would be owned types T, not references &T or &mut T, unless they are &'static T types. That's not the case in your code as you've instantiated a struct inside main (albeit erroneously annotated as having a 'static lifetime) and then tried to move a mutable borrow of a field inside your closure.
I am in a &mut self function, I have a member field that is a Vec<u8>. I want to call a windows xxxA function (via the excellent winapi crate). I have no choice on the fn signature, it is implementing a trait.
I think I need to make a CString. So I tried
fn flush(&mut self) -> std::io::Result<()> {
unsafe {
let str = CString::new(self.buf).unwrap();
OutputDebugStringA(str.as_ptr());
}
Ok(())
}
this doesn't work.
error[E0507]: cannot move out of `self.buf` which is behind a mutable reference
--> src\windbg.rs:51:36
|
51 | let str = CString::new(self.buf).unwrap();
| ^^^^^^^^ move occurs because `self.buf` has type `std::vec::Vec<u8>`, which does not implement the `Copy` trait
I've read the explain of this but none of the 3 suggested solutions seem possible.
Here is the whole struct:
struct WinDbgWriter {
buf: Vec<u8>,
}
use std::io::Write;
impl std::io::Write for WinDbgWriter {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.buf.extend_from_slice(buf);
Ok(buf.len())
}
fn flush(&mut self) -> std::io::Result<()> {
unsafe {
let str = CString::new(self.buf).unwrap();
OutputDebugStringA(str.as_ptr());
}
Ok(())
}
}
If we take your minimized case and try to borrow self.mut to avoid moving it (transferring its ownership), we get a new error which has a suggestion:
error[E0277]: the trait bound `Vec<u8>: From<&Vec<u8>>` is not satisfied
--> src/lib.rs:9:33
|
9 | let _str = CString::new(&self.buf).unwrap();
| ^^^^^^^^^
| |
| the trait `From<&Vec<u8>>` is not implemented for `Vec<u8>`
| help: consider adding dereference here: `&*self.buf`
|
= help: the following implementations were found:
<Vec<T> as From<&[T]>>
<Vec<T> as From<&mut [T]>>
<Vec<T> as From<BinaryHeap<T>>>
<Vec<T> as From<Box<[T]>>>
and 6 others
= note: required because of the requirements on the impl of `Into<Vec<u8>>` for `&Vec<u8>`
If we follow that suggestion, or explicitly coerce self.buf to a &[u8], then the code compiles.
CString::new takes an argument of some type Into<Vec<u8>>, but self.buf is, at this point of type &Vec<u8> because of it being accessed through a &self borrow, and there's no impl Into<Vec<u8>> for &Vec<u8>.
Let's try to compile this code:
use std::cell::RefCell;
struct Foo {
v: Vec<RefCell<u8>>,
}
impl Foo {
fn f(&self, i: usize) {
let t = &mut *self.v[i].borrow_mut();
//let t = &mut *{self.v[i].borrow_mut()}; //compiled ok
}
}
fn main() {}
Compilation error:
error[E0596]: cannot borrow field `self.v` of immutable binding as mutable
--> src/main.rs:9:23
|
8 | fn f(&self, i: usize) {
| ----- use `&mut self` here to make mutable
9 | let t = &mut *self.v[i].borrow_mut();
| ^^^^^^ cannot mutably borrow field of immutable binding
Why does this code require adding &mut self to function signature in order to compile?
This is a known issue where IndexMut is sometimes selected when Index should actually be used.
Your workaround of using {} is reasonable, but you can also use Index explicitly:
use std::cell::RefCell;
fn f(v: Vec<RefCell<u8>>) {
use std::ops::Index;
let _t = &mut v.index(0).borrow_mut();
}
fn main() {}
See also:
Why does a mutable borrow of a closure through DerefMut not work?
How to use `BorrowMut` contained within `RefCell`?
Another workaround is to explicitly call RefCell::borrow_mut(&v[0]).
I am having some trouble with the dynamic dispatch pointer types in Rust. I want to convert a value of type Box<MyTrait> to &mut MyTrait to pass to a function. For example, I tried:
use std::borrow::BorrowMut;
trait MyTrait {
fn say_hi(&mut self);
}
struct MyStruct { }
impl MyTrait for MyStruct {
fn say_hi(&mut self) {
println!("hi");
}
}
fn invoke_from_ref(value: &mut MyTrait) {
value.say_hi();
}
fn main() {
let mut boxed_trait: Box<MyTrait> = Box::new(MyStruct {});
invoke_from_ref(boxed_trait.borrow_mut());
}
This fails with the following error:
error: `boxed_trait` does not live long enough
--> <anon>:22:5
|
21 | invoke_from_ref(boxed_trait.borrow_mut());
| ----------- borrow occurs here
22 | }
| ^ `boxed_trait` dropped here while still borrowed
|
= note: values in a scope are dropped in the opposite order they are created
Strangely enough, this works for &MyTrait but not for &mut MyTrait. Is there any way I can get this conversion to work in the mutable case?
I think you're running into a limitation of the current compiler's lifetime handling. borrow_mut, being a function, imposes stricter lifetime requirements than necessary.
Instead, you can take a mutable borrow to the box's interior by first dereferencing the box, like this:
fn main() {
let mut boxed_trait: Box<MyTrait> = Box::new(MyStruct {});
invoke_from_ref(&mut *boxed_trait);
}