Skip to content

← Modules, Visibility, Testing and Docs step 9 of 22

Medium Primitives

The preludes — all five of them

“Where did Vec come from?” is a real question with a precise answer. You never imported it, there is no use at the top of your file, and yet it is there — along with Option, String, Box, Iterator and about thirty more.

They come from a prelude: a set of names the compiler injects into every module. There are five of them, and knowing which is which explains why some code from Stack Overflow needs an import you don’t.

prelude what it holds can you turn it off?
standard library Vec, Option, Iterator, … — edition-dependent yes, #![no_implicit_prelude]
extern the crates you depend on, by name no
language bool, char, str, u8i128, usize, f32, f64 no
macro_use macros from #[macro_use] extern crate 2015-era, mostly gone
tool the clippy and rustfmt attribute namespaces no

The task

pub fn needs_import(edition: &str, names: Vec<String>) -> Vec<String>

Return, in input order, the names that are not already in scope for that edition — the ones you would have to write a use for.

Editions are "2015", "2018", "2021", "2024". Anything else — including the literal "none" — models #![no_implicit_prelude]: no standard-library prelude at all.

The edition deltas are the clearest thing an edition ever does

Editions are usually explained abstractly. Here is a concrete, memorable instance:

  • 2015 and 2018 share std::prelude::v1.
  • 2021 added TryFrom, TryInto and FromIterator. This is why tutorials written before 2021 open with use std::convert::TryInto; and why copying that line into a modern file gets you an unused_imports warning.
  • 2024 added Future and IntoFuture.

This harness compiles at edition 2024, so all five of those are already in scope for you.

Two traps in the test data

bool and u32 are never imported, in any edition, ever. They are in the language prelude, which is part of the language rather than a library. #![no_implicit_prelude] does not remove it — and a handful of compiler-intrinsic macros survive that attribute too.

HashMap, Rc and Ordering have never been in any prelude. They are extremely common and they still need use std::collections::HashMap;, use std::rc::Rc;, use std::cmp::Ordering;. Frequency of use is not the criterion; the prelude is deliberately small, because every name in it is a name that can shadow yours.

Which, incidentally, is the last piece of the previous item: a user glob beats the standard prelude. use my_prelude::*; that happens to export a Result silently replaces std::result::Result for that module.