extern crate vs use in Rust: How Not to Confuse Them and Write Correctly

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

extern crate and use in Rust: What's the Catch and How to Avoid Pitfalls

\n\n

If you've ever written even a couple of lines in Rust, you've certainly encountered the extern crate and use constructs. At first glance, they seem to do the same thing — bring in external code. But the devil, as always, is in the details. This question is among the most popular on Stack Overflow (thousands of views!), and beginners constantly get confused by it. Let's finally figure out once and for all how extern crate differs from use, where the magic happens, and how to avoid typical mistakes.

\n\n

The Short Version: What's What

\n\n

Imagine your Rust project is a big house. extern crate is the delivery of building materials to the site. You tell the compiler: "Hey, I want to use this box of bricks (crate), bring it over." Without this command, the compiler won't even know an external library exists.

\n\n

use is the internal navigation inside the house. You say: "I want the door from this room (module) to lead directly to the kitchen (a specific type or function)." use creates aliases (short paths) to already known modules and types, so you don't have to write the full path every time.

\n\n

Simply put: extern crate answers the question "what can we even use?", while use answers "how can we conveniently refer to it?".

\n\n

Historical Context: Why Everyone Gets Confused

\n\n

The confusion didn't come out of nowhere. In older versions of Rust (before the 2018 edition), extern crate was mandatory for any external crate. It looked like this:

\n\n
// Rust 2015 — old style\nextern crate serde;\nuse serde::{Serialize, Deserialize};
\n\n

Starting with Rust 2018 edition, the compiler learned to find dependencies from Cargo.toml on its own. Now, writing extern crate for most crates is not necessary. It's enough to just add the dependency to Cargo.toml and immediately use use:

\n\n
// Rust 2018+ — new style (extern crate is not mandatory)\nuse serde::{Serialize, Deserialize};
\n\n

This is where the nightmare for beginners begins. They see old examples where extern crate is used, new ones where it isn't, and try to figure out when it's actually needed. Spoiler: it is needed, but in very rare cases.

\n\n

When extern crate Is Still Needed (And This Is Important!)

\n\n

There are three situations where you can't do without extern crate:

\n\n
    \n
  • Linking to system libraries via #[link] — if you're writing bindings to C/C++ code and using the #[link(name = "sqlite3")] attribute, then extern crate is mandatory.
  • \n
  • Global macros — some crates (e.g., log) export macros that need to be visible throughout the entire program. In Rust 2018, you need to write extern crate log; for this.
  • \n
  • Building with non-standard crate names — if you use extern crate my_crate as foo; to rename a crate.
  • \n
\n\n

In all other cases, extern crate is a relic of the past. But many developers continue to write it out of habit, and beginners copy code from old tutorials.

\n\n

Top 5 Mistakes When Working with extern crate and use

\n\n

Mistake #1: Using extern crate where it's not needed

\n\n

The most common problem. You add a crate to Cargo.toml, then write extern crate rand; — and the code works. But it's an extra line. In modern projects (Rust 2018+), it only clutters the code and can confuse other developers.

\n\n
// Bad (redundant in Rust 20                

Blogs

Book Recommendations