Skip to content

Commit 937ff78

Browse files
committed
Rust Code Order: Use order
1 parent 603e090 commit 937ff78

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

_posts/2019-01-17-how-to-order-rust-code.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,57 @@ right next to the functions they are needed for.
6868
> [I] love to read types upfront
6969
> (if you know the set of fields, you know all potential methods that can exists)
7070
71+
### Where to put `use` statements?
72+
73+
To use an item (type, trait, function, etc.) that is not in scope
74+
you can either refer to it by its full path
75+
(e.g., `std::collections::HashMap`)
76+
or import it using
77+
`use std::collections::HashMap;`
78+
after which you can refer it as just `HashMap`.
79+
The issue is:
80+
Where to put these `use` statements?
81+
82+
One typical approach is to put them all at the top of the file.
83+
This "wall of imports"
84+
is what you also see in many other programming languages.
85+
This is a good idea if the only location you can put import statements
86+
is at the root level
87+
and especially if the file contains one "main item"
88+
(e.g., if `foo.java` contains import statements followed by `class Foo { … }`).
89+
In Rust, however,
90+
you don't often have just one item at the root level.
91+
You have a `foo.rs`
92+
that contains a `struct Foo { … }`,
93+
various `impl Bar for Foo { … }` blocks,
94+
possibly some free functions,
95+
and in many cases even unit tests.
96+
So, we should rethink where to put these `use` lines!
97+
98+
One approach I've taken previously is
99+
to keep `use`s as close to the area they are needed as possible.
100+
If I have a function that reads five files,
101+
I add a `use std::fs::File;` at the beginning _of that function._
102+
Sadly,
103+
this breaks down when you want to import a type
104+
to use it in a function's/method's signature or as a field type in a struct:
105+
In that case,
106+
the use `use` needs to be on the level _above_ the usage point
107+
(i.e., on the level of the function/trait/struct definition).
108+
Additionally,
109+
if you have `use std::sync::Arc` above one struct,
110+
it becomes available in the general scope.
111+
So, your next struct that uses `Arc`
112+
doesn't need to have a second instance of that `use` line.
113+
114+
This all lead me to the point where
115+
I often just go back to collecting `use`s at the top of the file.
116+
I will however not write single `use` lines for all the items I want to use,
117+
but instead
118+
119+
- only import the module when I use various items but each of them only a few times (e.g. `use std::sync;` and refer to `sync::Arc` and `sync::Mutex`.)
120+
- make use of Rust's nested imports (e.g. `use std::{error::Error, fs, io::{self, Read}};)`.
121+
71122
### Split public and private interfaces
72123

73124
When the entry file of a package or module[^1] gets to long,

0 commit comments

Comments
 (0)