We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Modules, Visibility, Testing and Docs step 7 of 22
Three namespaces: types, values, and macros
Here is the hidden mechanism behind a dozen otherwise-arbitrary rules. Rust has three namespaces, and a name is only in conflict with another name in the same one.
| namespace | inhabitants |
|---|---|
| type | structs, enums, unions, traits, type aliases, modules, primitives |
| value | functions, constants, statics, and struct/variant constructors |
| macro |
macro_rules! macros, attribute and derive macros |
Once you know this, several things stop being coincidences.
-
OptionandSomeare different names because one is a type and one is a constructor. They could not share a name space and both be spelledOption. -
use std::io;anduse std::io::Result;do not clash:iois a module (type namespace) andResultis a type — different names entirely, no conflict. -
println!needs the!partly because macros live somewhere else. A function calledprintlnwould be an unrelated name.
The task
pub fn collisions(decls: Vec<String>) -> Vec<String>
Given normalised declarations, return the sorted, deduplicated set of names declared twice in the same namespace. Anything unrecognised is ignored.
| form | occupies |
|---|---|
struct Name {} |
type |
struct Name; |
type and value |
struct Name() |
type and value |
enum Name, trait Name, type Name, union Name, mod Name |
type |
fn Name, const Name, static Name |
value |
macro_rules! Name |
macro |
The line that catches everybody
struct Foo {} + fn Foo -> no conflict
struct Foo; + fn Foo -> E0428, `Foo` is defined multiple times
A braced struct is a type only. A unit struct is a type and a value,
because Foo on its own is an expression that produces one. A tuple struct is a
type and a value too, because Foo(3) is a function call — the constructor
really is a function, and you can pass Foo to map.
So this innocent-looking pair does not compile:
struct Config; // took the value namespace, silently
fn Config() -> Config { Config } // E0428
…and the error message talks about Config being “defined multiple times”,
which is baffling until you know that the unit struct quietly claimed a slot you
did not know existed.
Three flavours of collision
Worth being able to tell apart, because the fix differs:
- E0428 — defined multiple times. Two items with the same name in the same namespace. Rename one.
-
E0255 — the name is defined multiple times. An import collides with an
item you declared. Use
ason the import, or move the item. -
E0252 — the name is defined multiple times. Two imports collide.
asone of them.
And E0659 — from the previous item — is the fourth, deferred kind: two globs, error only at use.
Contract
Declarations arrive already normalised, with single spaces, in the exact forms
in the table. macro_rules! keeps its !. Return names sorted; a name that
collides in two namespaces at once still appears once.
Stuck?
Rust reference solution
Sign in to attempt this problem and reveal the reference solution.