Skip to content

Rust Error E0252: The Name Is Defined Multiple Times (Two Imports)

E0252 means two use lines bring in the same name. The textbook case is use std::fmt::Result; plus use std::io::Result;: two different types, both called Result. Others are fmt::Error and io::Error, or the two Write traits. It’s a very common error and an easy one to fix, usually by changing one or two use lines. rustc 1.97 still reports it under its own code, E0252. It’s part of the compiler errors guide.

error[E0252]: the name `Result` is defined multiple times
--> src/main.rs:2:5
|
1 | use std::fmt::Result;
| ---------------- previous import of the type `Result` here
2 | use std::io::Result; // ❌ a second `Result`
| ^^^^^^^^^^^^^^^ `Result` reimported here
|
= note: `Result` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
2 | use std::io::Result as OtherResult; // ❌ a second `Result`
| ++++++++++++++

This is the program that produces it:

use std::fmt::Result;
use std::io::Result; // ❌ a second `Result`
struct Temperature {
celsius: i32,
}
impl std::fmt::Display for Temperature {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result {
write!(f, "{} °C", self.celsius)
}
}
fn parse_temperature(text: &str) -> Result<Temperature> {
match text.trim().parse() {
Ok(celsius) => Ok(Temperature { celsius }),
Err(_) => Err(std::io::Error::other("not a number")),
}
}
fn main() {
match parse_temperature("21") {
Ok(t) => println!("{}", t),
Err(e) => println!("error: {}", e),
}
}

rustc prints four more errors after this one: E0107 (“type alias takes 0 generic arguments”), two E0308 mismatched types, and an E0277. Don’t chase them. Rust kept the first import, so every Result in the file now means fmt::Result, and parse_temperature no longer makes sense. Fix E0252 and they all go away.

rustc points at two use lines:

  1. The --- line (line 1): “previous import of the type Result here”. This one came first, so it’s the one Rust keeps.
  2. The ^^^ line (line 2): “Result reimported here”. The second import tries to take the same name.
  3. The help: suggests renaming the second import with as.

std::fmt::Result and std::io::Result are really different. fmt::Result is a plain Result<(), fmt::Error>, used by Display and Debug. io::Result<T> is Result<T, io::Error>, used by files and the network. Same name, different jobs.

It’s like saving two contacts as “Mom” on your phone, your mother and your partner’s mother. When you tap “Mom”, the phone has to know which one to call. You add a word to one of them, or you save them as “Mom (Ana)” and “Mom (Lee)”.

Inside one module, every name points at exactly one item. A use line doesn’t copy anything; it adds a short name for an item that lives elsewhere. Two use lines that add the same short name would make every later Result ambiguous, so Rust stops at the import instead of guessing at each use.

E0252 is one of three siblings with the same headline: E0255 is a use line against your own item, and E0428 is two of your own items. The rule behind all three is “one name, one thing, per module”. See Modules.

Fix 1: Import the modules and write fmt:: and io::

Section titled “Fix 1: Import the modules and write fmt:: and io::”

Choose this most of the time, and always for Result and Error. Import the parent modules, then write the module name in front. Every use now says which Result it is. The Rust Book recommends this style for exactly this case:

use std::fmt;
use std::io;
struct Temperature {
celsius: i32,
}
impl fmt::Display for Temperature {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} °C", self.celsius)
}
}
fn parse_temperature(text: &str) -> io::Result<Temperature> {
match text.trim().parse() {
Ok(celsius) => Ok(Temperature { celsius }),
Err(_) => Err(io::Error::other("not a number")),
}
}
fn main() {
for input in ["21", " -4 ", "warm"] {
match parse_temperature(input) {
Ok(t) => println!("{}", t),
Err(e) => println!("error: {}", e),
}
}
}

Output:

21 °C
-4 °C
error: not a number
▶ Try it Yourself

Bonus: the plain Result<T, E> from the prelude is still free to use, without any import.

Choose this when you use one of the two types a lot and want a short name for it. This is rustc’s suggestion. Pick a name that says where it comes from, like IoResult, rather than OtherResult:

use std::fmt::Result;
use std::io::Result as IoResult;
struct Temperature {
celsius: i32,
}
impl std::fmt::Display for Temperature {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result {
write!(f, "{} °C", self.celsius)
}
}
fn parse_temperature(text: &str) -> IoResult<Temperature> {
match text.trim().parse() {
Ok(celsius) => Ok(Temperature { celsius }),
Err(_) => Err(std::io::Error::other("not a number")),
}
}
fn main() {
match parse_temperature("21") {
Ok(t) => println!("{}", t),
Err(e) => println!("error: {}", e),
}
}

Output:

21 °C
▶ Try it Yourself

A plain Result that secretly means fmt::Result can surprise the next reader, so Fix 1 is usually clearer. as shines with long names, like use std::collections::BTreeMap as Map;.

Choose this for traits you only import to call their methods. The two Write traits are the classic: fmt::Write lets you write! into a String, io::Write lets you write! to stdout or a file. Importing both by name clashes:

error[E0252]: the name `Write` is defined multiple times
--> src/main.rs:2:5
|
1 | use std::fmt::Write;
| --------------- previous import of the trait `Write` here
2 | use std::io::Write; // ❌ a second `Write`
| ^^^^^^^^^^^^^^ `Write` reimported here
|
= note: `Write` must be defined only once in the type namespace of this module
help: you can use `as` to change the binding name of the import
|
2 | use std::io::Write as OtherWrite; // ❌ a second `Write`
| +++++++++++++

The broken program:

use std::fmt::Write;
use std::io::Write; // ❌ a second `Write`
fn main() {
let mut report = String::new();
write!(report, "{} tests passed", 12).unwrap();
let mut out = std::io::stdout();
writeln!(out, "{}", report).unwrap();
}

You never write Write yourself here; you only need its methods. as _ imports a trait without giving it a name, so nothing can clash, and both sets of methods still work:

use std::fmt::Write as _;
use std::io::Write as _;
fn main() {
let mut report = String::new();
write!(report, "{} tests passed", 12).unwrap();
let mut out = std::io::stdout();
writeln!(out, "{}", report).unwrap();
}

Output:

12 tests passed
▶ Try it Yourself

If you need to name one of them, for example in fn log(w: &mut impl io::Write), combine this with Fix 1: use std::io; and write io::Write. See Traits.

Fix 4: Remove a duplicate import of the same item

Section titled “Fix 4: Remove a duplicate import of the same item”

Choose this when both lines import the very same thing, which often happens after merging code or when your editor adds an import you already had:

error[E0252]: the name `HashMap` is defined multiple times
--> src/main.rs:2:24
|
1 | use std::collections::HashMap;
| ------------------------- previous import of the type `HashMap` here
2 | use std::collections::{HashMap, HashSet}; // ❌ `HashMap` again
| ^^^^^^^--
| |
| `HashMap` reimported here
| help: remove unnecessary import

The broken program:

use std::collections::HashMap;
use std::collections::{HashMap, HashSet}; // ❌ `HashMap` again
fn main() {
let mut stock: HashMap<&str, u32> = HashMap::new();
stock.insert("apples", 3);
let mut sold_out: HashSet<&str> = HashSet::new();
sold_out.insert("pears");
println!("apples: {}, sold out: {}", stock["apples"], sold_out.len());
}

Notice that the help is different: no as, just “remove unnecessary import”. Keep one line:

use std::collections::{HashMap, HashSet};
fn main() {
let mut stock: HashMap<&str, u32> = HashMap::new();
stock.insert("apples", 3);
let mut sold_out: HashSet<&str> = HashSet::new();
sold_out.insert("pears");
println!("apples: {}, sold out: {}", stock["apples"], sold_out.len());
}

Output:

apples: 3, sold out: 1
▶ Try it Yourself

See HashMaps and HashSet.

Error from two places. use std::fmt::Error; and use std::io::Error;, or use std::error::Error; next to use anyhow::Error;. Fix: use std::io; and write io::Error, or use anyhow::Error as AnyError;. See anyhow and thiserror.

Two crates with the same type name. use chrono::Duration; and use std::time::Duration; are a common pair in projects that handle dates. Fix: keep one short name and write the other one’s module, like chrono::Duration. See Date and Time.

Glob imports. use std::fmt::*; plus use std::io::*; gives no E0252 at the use lines. The trouble comes later, at the first Result, as an error without a code: error: `Result` is ambiguous. Fix: import the names you need explicitly, as in Fix 1.

  • E0255: a use line clashes with your own struct, enum or function of the same name.
  • E0428: two of your own items share a name, often from trying to overload a function.
  • E0432: unresolved import, when the use line points at something that doesn’t exist.
  • E0034: two traits in scope give a type methods with the same name.
  • E0308: mismatched types, one of the follow-up errors after a Result clash.
  • All compiler errors: the full list of error pages.

Quick check

1. You need fmt::Result and io::Result in the same file. Which imports are the usual clean choice?

2. You need the methods of both std::fmt::Write and std::io::Write, but never write the trait names yourself. What works?

3. rustc says HashMap is reimported here and suggests remove unnecessary import. What happened?

Score: 0 / 3