Type of a should be &mut [u8] instead of &mut &mut [u8], right?
![]()
Let me give more context:
vault_info.data is :
solana_account_info::AccountInfo
pub data: Rc<RefCell<&'a mut [u8]>, Global>
Type of a should be &mut [u8] instead of &mut &mut [u8], right?
![]()
Let me give more context:
vault_info.data is :
solana_account_info::AccountInfo
pub data: Rc<RefCell<&'a mut [u8]>, Global>
have you accidentally imported std::borrow::BorrowMut into the scope?
I didn't import std::borrow::BorrowMut into the scope
you have RefCell<&mut [u8]>, which is different from RefCell<[u8]>.
the former gives &mut &mut [u8], the latter gives &mut [u8].
Doesn't *vault_info.data.borrow_mut() deref the inner one to [u8], and so we get only &mut u8 instead of `&mut &mut [u8]?
no.
NOTE of EDIT:
the following statements are incorrect.
RefCell::borrow_mut() returns a proxy type RefMut<'_, T>, not the actual reference type &mjt T. see the answer below for the full detail.
/EDIT
vault_info.data.borrow_mut() has type , dereference it once gives &mut &mut [u8]&mut [u8].
the type signature of RefCell::borrow_mut() is fn(self: &mut RefCell<T>) -> &mut TRefMut<'_, T>, which is a proxy for &mut T, in your case, T is &mut [u8], so &mut T is &mut &mut [u8].
if you want borrow_mut() to return a proxy of &mut [u8]&mut [u8], then T must be the DST [u8] itself, not the reference type &mut [u8].
this is not correct
there is no fn borrow_mut(self: &mut RefCell<T>) -> &mut T, that does not exist.
vault_info.data.borrow_mut() has type RefMut<'_, &mut [u8]>, not &mut &mut [u8]
there are only 3 methods with that name that are reachable :
the inherent method
RefCell::borrow_mut(self: &RefCell<T>) -> RefMut<'_, T>
and through the BorrowMut trait
<RefCell as BorrowMut>::borrow_mut(self: &mut RefCell<T>) -> &mut RefCell<T>
as well as
<Rc as BorrowMut>::borrow_mut(self: &mut Rc<U>) -> &mut Rc<U>
now, one may quicly notice <RefCell as BorrowMut>::borrow_mut(self: &mut RefCell<T>) -> &mut RefCell<T> is completely impossible to call because the RefCell is in an Rc, so you can't have a &mut to it.
it could absolutely be
<Rc as BorrowMut>::borrow_mut(self: &mut Rc<U>) -> &mut Rc<U>
in theory if vault_info was mutable and the BorrowMut trait was in scope.
in that case
vault_info.data.borrow_mut() would just be &mut Rc<RefCell<&'a mut [u8]>, Global>, and so would &mut *vault_info.data.borrow_mut(), and therefore a.
this is what he compiler will choose to do if you bring BorrowMut in scope, even if it can't get a &mut on the Rc, which is why you should not bring BorrowMut in scope.
but because you have not made the mistake of putting BorrowMut in scope, you can know for sure this is not a call to a BorrowMut trai method. so it must be the inherent method
RefCell::borrow_mut(self: &RefCell<T>) -> RefMut<'_, T>
therefore vault_info.data.borrow_mut() is RefMut<'_, &mut [u8]>,
*vault_info.data.borrow_mut() is &mut [u8] (because of RefMut's Deref[Mut] implementations
and logically &mut *vault_info.data.borrow_mut() is &mut &mut [u8]
which is what is happening here.
code showing the impact of importing the BorrowMut trait :
use std::cell::RefCell;
use std::rc::Rc;
struct Vi<'a> {
data: Rc<RefCell<&'a mut [u8]>>
}
fn test_immut_rc(vault_info : &Vi) {
use std::borrow::BorrowMut;
// tries to use `<Rc as BorrowMut>::borrow_mut`
// but fails because it can't get a &mut to the Rc
let a = &mut *vault_info.data.borrow_mut();
}
fn test_mut_rc(vault_info : &mut Vi) {
use std::borrow::BorrowMut;
// uses `<Rc as BorrowMut>::borrow_mut` because it has &mut
let a : &mut Rc<RefCell<&mut [u8]>> = &mut *vault_info.data.borrow_mut();
}
fn test_refcell(vault_info : &Vi) {
// uses `RefCell::borrow_mut` (inherent, not trait method)
let a : &mut &mut [u8]= &mut *vault_info.data.borrow_mut();
}
Thanks, this is very clear and comprehensive.
sorry I showed the wrong answer.
RefMut<'a, T> is a proxy of &'a mut T, they have the same level of indirection. I substitute the fake type for the purpose of counting the references, and I don't want to explain the desugaring of the dereference operator using the DerefMut trait.
I edited my post to avoid confusion.