As I understand it, there's a type namespace (struct
s, enum
s, trait
s), a value namespace (variables, const
s, functions), a macro namespace and a lifetime namespace. If the rules are explicitly defined, I don't know where. There are some interesting quirks...
Various examples of naming conflicts and shadowing
No overlapping function names or struct
names:
fn val() {}
fn val(b: u8) {}
// Error: `val` must be defined only once in the value namespace of this block
// (same for two structs, or a struct and a function, with the same name)
This will bite you if you name a function the same as a tuple struct
type (since that creates an entry in value namespace as well, for the constructor):
struct TupleStruct(usize, isize);
fn TupleStruct(f: f32) -> bool { false }
// Error: `TupleStruct` must be defined only once in the value namespace of this block
Variables can shadow function and struct
names though (even if the variable comes first!):
fn main() {
let val = 5;
fn val() {}
val();
// Error: call expression requires function
}
However there's an explicit exception for tuple struct
constructors!
fn main() {
struct TupleStruct(usize, isize);
let TupleStruct = 5;
// Error: cannot be named the same as a tuple struct
}
And you can't shadow a const
...
fn main() {
const Foo: bool = true;
let Foo = -2;
// Error: `Foo` is interpreted as a constant, not a new binding
}
And the case of unit struct
s, instead of a fn
constructor you get a const
(I believe; the error message does distinguish it as a unit struct
).
fn main() {
struct Unit;
let Unit = -3;
// Error: `Unit` is interpreted as a unit struct, not a new binding
// (`fn` gives the same "value namespace" error as with normal or Tuple structs)
}
Finally as @scottmcm said, you can create a (non-tuple, non-unit) struct
and fn
with the same name currently, as they are in difference namespaces (so this would be a breaking change... or confusing with a new namespace I suppose):
struct StructStruct { a: usize, b: isize }
fn StructStruct(_: f64) -> () {()}
// compiles