A glob import (use geometry::*;) pulls in every public name from a module — including ones you might already be defining yourself. When the names collide, Rust doesn't raise an error: your own local item silently wins and the imported one is shadowed. The code keeps compiling, calling the wrong function with perfectly valid arguments; you get only warnings about unused code.
mod geometry {
pub fn area(radius: f64) -> f64 {
3.14159 * radius * radius
}
}
use geometry::*;
fn area(side: f64) -> f64 {
side * side
}
println!("circle area: {:.2}", area(2.0));
// prints 4.00, not 12.57 -- the local area() shadowed the glob import
// warning: unused import: `geometry::*`A crate is the smallest amount of code the Rust compiler considers at one time — either a binary (with a main function) or a library. Within a crate, mod declares a module to organize related code, and every item (function, struct, module) is private to its parent module by default; pub explicitly opts an item into visibility outside that module. use brings a path into scope so it doesn't need to be fully qualified every time it's referenced.
Declaring modules and privacy
Without pub, an item is only reachable from within its own module and its descendants — a caller outside gets a compile error, not a runtime surprise.
mod kitchen {
pub fn cook() { // pub: visible outside this module
season(); // private fns ARE visible to code inside their own module
}
fn season() { // private: only usable inside `kitchen`
println!("seasoning");
}
}
kitchen::cook(); // fine — cook is pub
// kitchen::season(); // COMPILE ERROR: season is privateuse: bringing paths into scope
Without use, every reference to an item needs its full module path; use imports a shorter name into the current scope, similar in spirit to an import statement in other languages.
use std::collections::HashMap; // now HashMap works without the full path
let mut map = HashMap::new(); // instead of std::collections::HashMap::new()Explicit imports behave differently, which is the reason to prefer them: importing geometry::area by name and then defining your own area is a hard compile error (E0255), not a silent shadow. Renaming the import with as makes both functions available and unambiguous:
use geometry::area as circle_area;
fn area(side: f64) -> f64 {
side * side
}
println!("circle area: {:.2}", circle_area(2.0)); // circle area: 12.57
println!("square area: {:.2}", area(2.0)); // square area: 4.00Crates: binaries, libraries, and Cargo workspaces
A binary crate has a main.rs with a main function and compiles to an executable; a library crate has a lib.rs and compiles to code other crates can depend on. A Cargo workspace groups several related crates that share one Cargo.lock and target directory, common in larger projects split into multiple packages.