Search code examples
rusttortype-annotation

explicit type annotation in Rust with private type


I want to find out the type of a variable in 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(())
}

In order to find out the type of the variable tor_client, I used std::any::type_name:

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

[...]

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

The type printed to stdout is arti_client::client::TorClient<tor_rtcompat::PreferredRuntime>.

I naively assumed that I can now declare the variable with that explicit type annotation:

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(())
}

However, the compiler absolutely does not like that:

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

What do I do wrong? I assume that the arti_client::client module is private for a reason...

Background on why I want to find out the type and use explicit type annotation: I want to pass a reference to that variable to a custom function. As far as I understand it, I can not / should not declare a function parameter without knowing the type.


Solution

  • The client module is private, but this doesn't mean that you can't access the struct.

    To see the exact type as it is intended to be used, you can check the documentation for the method in question; the signature of the method is this:

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

    where Self is an alias for arti_client::TorClient<tor_rtcompat::PreferredRuntime>.

    As you can see, this type is indeed the TorClient, as the type_name told you, but it is scoped directly in the arti_client crate root - not in the client module. To understand this difference, let's check the source:

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

    So:

    • module client is indeed private;
    • struct TorClient is defined there, and that's what type_name shows;
    • but it is reexported from the crate root, so you can use it without accessing private module.