ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Rust复杂的表达式解析结果探讨

2022-02-25 13:59:03  阅读:204  来源: 互联网

标签:mut account methods borrow pub Rust 解析 data 表达式


在上文Solana项目学习(一):Hello World_biakia0610的专栏-CSDN博客中,我们学习了solana的helloworld例子,在代码最后一部分,有一个非常复杂的表达式:

greeting_account.serialize(&mut &mut account.data.borrow_mut()[..])?;

这里的&mut &mut account.data.borrow_mut()[..] 到底是返回什么呢? 这篇文章会尝试进行详细探讨。

首先,account是solana官方数据类型AccountInfo

#[derive(Clone)]
pub struct AccountInfo<'a> {
    /// Public key of the account
    pub key: &'a Pubkey,
    /// Was the transaction signed by this account's public key?
    pub is_signer: bool,
    /// Is the account writable?
    pub is_writable: bool,
    /// The lamports in the account.  Modifiable by programs.
    pub lamports: Rc<RefCell<&'a mut u64>>,
    /// The data held in this account.  Modifiable by programs.
    pub data: Rc<RefCell<&'a mut [u8]>>,
    /// Program that owns this account
    pub owner: &'a Pubkey,
    /// This account's data contains a loaded program (and is now read-only)
    pub executable: bool,
    /// The epoch at which this account will next owe rent
    pub rent_epoch: Epoch,
}

我们可以看到data是个Rc<RefCell<&'a mut u64>>类型。那么当我们调account.data.borrow_mut()的时候,实际发生了什么呢?

在RC官方文档中有如下描述:

//! `Rc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
//! so you can call `T`'s methods on a value of type [`Rc<T>`][`Rc`]. To avoid name
//! clashes with `T`'s methods, the methods of [`Rc<T>`][`Rc`] itself are associated
//! functions, called using [fully qualified syntax]:

所以account.data.borrow_mut()调用的其实是被RC包裹的RefCell<&mut [u8]>的方法。

下面我们看下RefCell中的borrow_mut()

    #[stable(feature = "rust1", since = "1.0.0")]
    #[inline]
    #[track_caller]
    pub fn borrow_mut(&self) -> RefMut<'_, T> {
        self.try_borrow_mut().expect("already borrowed")
    }

可以看到返回的是一个RefMut类型。因此,account.data.borrow_mut()[..]其实是对RefMut类型做[..]操作,而[..]操作是什么呢?它其实是语法糖,真实的操作是

*(account.data.borrow_mut().index_mut(..))

这时候其实是调用RefMut的index_mut(..)方法,然后找了一圈发现RefMut并没有这个方法。这时候按理说应该会编译报错啊,但是实际是运行成功的。那为什么呢?其实是Rust编译器帮我们智能解析了表达式,下面是Rust官方文档中的描述:

When looking up a method call, the receiver may be automatically dereferenced or borrowed in order to call a method. This requires a more complex lookup process than for other functions, since there may be a number of possible methods to call. The following procedure is used:

The first step is to build a list of candidate receiver types. Obtain these by repeatedly dereferencing the receiver expression's type, adding each type encountered to the list, then finally attempting an unsized coercion at the end, and adding the result type if that is successful. Then, for each candidate T, add &T and &mut T to the list immediately after T.

For instance, if the receiver has type Box<[i32;2]>, then the candidate types will be Box<[i32;2]>&Box<[i32;2]>&mut Box<[i32;2]>[i32; 2] (by dereferencing), &[i32; 2]&mut [i32; 2][i32] (by unsized coercion), &[i32], and finally &mut [i32].

Then, for each candidate type T, search for a visible method with a receiver of that type in the following places:

  1. T's inherent methods (methods implemented directly on T).
  2. Any of the methods provided by a visible trait implemented by T. If T is a type parameter, methods provided by trait bounds on T are looked up first. Then all remaining methods in scope are looked up.

大意就是Rust会对不匹配的表达式进行各种尝试,比如引用、解引用等。

*(account.data.borrow_mut().index_mut(..))

这里虽然RefMut并没有index_mut方法,但是Rust会对RefMut进行解引用,得到内部的&mut [u8],而&mut [u8]是可以执行index_mut方法的,返回的还是个&mut [u8]。因此上面的表达式就变成了

*(&mut [u8])

最终就是一个[u8]类型

因此&mut &mut account.data.borrow_mut()[..]的结果是&mut &mut [u8]。

参考:

​​​​​​rust - Trouble understanding &mut &mut reference - Stack Overflow

Method call expressions - The Rust Reference

IndexMut in std::ops - Rust

标签:mut,account,methods,borrow,pub,Rust,解析,data,表达式
来源: https://blog.csdn.net/biakia0610/article/details/123131164

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有