Search code examples
randomrustscopetraits

Why does this rand use statement work in rust?


Following the example in the Rust book using its suggested rand = "0.6.0", I get code that looks like this:

use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1, 101);

    println!("The secret number is: {}", secret_number);
}

Everything the book says later on in its chapter on modules suggests that if you do a use rand::Rng; as above, you'll be able to use Rng. If that happens to be a module itself, you can use submodules with Rng::submodule. If that happens to be a type, you just use it as Rng. In the code above however, we never use Rng anywhere.

Instead, we use the seemingly unrelated rand::thread_rng(). From what I understand, since rand is the name of the top level crate, we should be able to use it, even without the use statement that doesn't appear to do anything.

Instead, for some reason, the program will fail to compile without the use statement. This is really confusing. I wish the book did a better job explaining what was happening there.

Why do we need the use statement? Why are we not using Rng? How is it related to rand::thread_rng()?

I come from a Python background, so I'm used to the idea that if you import threading, you're using threading.something. If you import django.utils, you're using django.utils.something. This seems like an import of django.utils where you're using the totally unrelated django.urls.


Solution

  • You cannot call trait methods unless the trait is in scope.

    In the code above however, we never use Rng anywhere.

    You're using Rng. gen_range() is a trait method defined by the Rng trait so Rng must be in scope for you to call gen_range().

    The nitty gritty details: rand::thread_rng() returns ThreadRng which implements RngCore and gets an Rng implementation because of the generic blanket impl impl<R> Rng for R where R: RngCore + ?Sized.