Rust 中具有私有类型的显式类型注释

explicit type annotation in Rust with private type

我想找出 Rust 中变量的类型:

use anyhow::Result;
use arti_client::{TorClient, TorClientConfig};
extern crate tokio;

#[tokio::main]
async fn main() -> Result<()> {
    let config = TorClientConfig::default();
    let tor_client = TorClient::create_bootstrapped(config).await?;

    // What is the type of `tor_client`?

    Ok(())
}

为了找出变量tor_client的类型,我使用了std::any::type_name:

use std::any::type_name;
fn type_of<T>(_: T) -> &'static str {
    type_name::<T>()
}

[...]

println!("{}", type_of(tor_client));

打印到标准输出的类型是arti_client::client::TorClient<tor_rtcompat::PreferredRuntime>

我天真地假设我现在可以使用显式类型注释声明变量:

use anyhow::Result;
use arti_client::{TorClient, TorClientConfig};
extern crate tokio;

#[tokio::main]
async fn main() -> Result<()> {
    let config = TorClientConfig::default();
    let tor_client: arti_client::client::TorClient<tor_rtcompat::PreferredRuntime> =
        TorClient::create_bootstrapped(config).await?;
    
    Ok(())
}

然而,编译器绝对不喜欢这样:

error[E0603]: module `client` is private
   --> src/main.rs:52:34
    |
52  |     let tor_client: arti_client::client::TorClient<tor_rtcompat::PreferredRuntime> =
    |                                  ^^^^^^ private module
    |
note: the module `client` is defined here
   --> /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/arti-client-0.3.0/src/lib.rs:220:1
    |
220 | mod client;
    | ^^^^^^^^^^^


error: aborting due to previous error

我做错了什么?我认为 arti_client::client 模块是私有的是有原因的...

为什么我想找出类型并使用显式类型注释的背景:我想将对该变量的引用传递给自定义函数。据我了解,我不能/不应该在不知道类型的情况下声明函数参数。

client 模块是私有的,但这并不意味着您不能访问该结构。

要查看要使用的确切类型,您可以检查 documentation 以了解相关方法;该方法的签名是这样的:

pub async fn create_bootstrapped(config: TorClientConfig) -> Result<Self>

其中 Selfarti_client::TorClient<tor_rtcompat::PreferredRuntime> 的别名。

如您所见,此类型确实是 TorClient,正如 type_name 告诉您的那样,但它的作用域直接在 arti_client crate root 中 - 而不是在 client模块。要了解这种差异,让我们检查一下 source:

mod client;
// skipped
pub use client::{BootstrapBehavior, DormantMode, StreamPrefs, TorClient};

所以:

  • 模块client确实是私有的;
  • struct TorClient 在那里定义,这就是 type_name 显示的内容;
  • 但是它是从 crate root 重新导出的,所以你可以在不访问私有模块的情况下使用它。