Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Where is the recommended place to put `use` declarations in Rust?

Tags:

rust

Where is the recommended place to put use declarations? I couldn't find any decisive answer in the book, in FAQs, mailing lists or online forums. I'm beginning a new project in Rust and I'd prefer to get the right approach right away.

Is one of the two below approaches recommended? Is it only for "aliasing" stuff or does it do more, like initialize a module if it hasn't been used before?

use std::io;
use std::io::Write;

fn some_func() -> () {
    [...] // We assume we need std::io here
}

fn some_other_func() -> () {
    [...] // We assume we need std::io and std::io::Write here
}

OR

fn some_func() -> () {
    use std::io;
    [...] // We assume we need std::io here
}

fn some_other_func() -> () {
    use std::io;
    use std::io::Write;
    [...] // We assume we need std::io and std::io::Write here
}
like image 885
achedeuzot Avatar asked Aug 10 '17 16:08

achedeuzot


People also ask

How does use work in Rust?

Usually a use keyword is used to shorten the path required to refer to a module item. The keyword may appear in modules, blocks and even functions, usually at the top.

How do you import a module in Rust?

To import the module, we use the keyword mod , followed by the file name without the . rs extension. When a module is imported, it allows us to use any code that's marked as public in the file we're importing the module from. Note that the module must be imported before we use any of its code.


1 Answers

TL;DR: Like almost every other piece of software, it depends on what you are doing. The common style that I have observed (and prefer myself) is to put them at the top of the file and only moving them to narrower scope as needed.


Generally, I recommend starting by placing use statements directly after any extern crate and mod statements, separated by a blank line:

extern crate foo;
extern crate bar;

mod interesting;

use std::collections::HashMap;
use foo::Foo;
use bar::{Quux, moo};    
use interesting::something;    

// structs, functions, etc.

I base this default on the fact that — most times — an import is used in multiple top-level items. Thus, it makes sense to only import it once.

There are times where imported traits have conflicting methods, and in those cases I scope the import to where it's needed. There are also cases where I'm heavily dealing with a single enum and wish to glob-import it to avoid re-stating the enum's name:

fn foo(e: MyEnum) {
    use MyEnum::*;

    match e {
        One => 1,
        Two => 2,
    }
}

In certain cases, conflicting use statements indicate that you are attempting too much in a single file and it should be split into separate files and then the use statements are no longer ambiguous.

like image 164
Shepmaster Avatar answered Oct 12 '22 23:10

Shepmaster