Namespaces

A namespace is a logical grouping of declared names. Names are segregated into separate namespaces based on the kind of entity the name refers to. Namespaces allow the occurrence of a name in one namespace to not conflict with the same name in another namespace.

Within a namespace, names are organized in a hierarchy, where each level of the hierarchy has its own collection of named entities.

There are several different namespaces that each contain different kinds of entities. The usage of a name will look for the declaration of that name in different namespaces, based on the context, as described in the name resolution chapter.

The following is a list of namespaces, with their corresponding entities:

An example of how overlapping names in different namespaces can be used unambiguously:


#![allow(unused)]
fn main() {
// Foo introduces a type in the type namespace and a constructor in the value
// namespace.
struct Foo(u32);

// The `Foo` macro is declared in the macro namespace.
macro_rules! Foo {
    () => {};
}

// `Foo` in the `f` parameter type refers to `Foo` in the type namespace.
// `'Foo` introduces a new lifetime in the lifetime namespace.
fn example<'Foo>(f: Foo) {
    // `Foo` refers to the `Foo` constructor in the value namespace.
    let ctor = Foo;
    // `Foo` refers to the `Foo` macro in the macro namespace.
    Foo!{}
    // `'Foo` introduces a label in the label namespace.
    'Foo: loop {
        // `'Foo` refers to the `'Foo` lifetime parameter, and `Foo`
        // refers to the type namespace.
        let x: &'Foo Foo;
        // `'Foo` refers to the label.
        break 'Foo;
    }
}
}

Named entities without a namespace

The following entities have explicit names, but the names are not a part of any specific namespace.

Fields

Even though struct, enum, and union fields are named, the named fields do not live in an explicit namespace. They can only be accessed via a field expression, which only inspects the field names of the specific type being accessed.

Use declarations

A use declaration has named aliases that it imports into scope, but the use item itself does not belong to a specific namespace. Instead, it can introduce aliases into multiple namespaces, depending on the item kind being imported.

Sub-namespaces

The macro namespace is split into two sub-namespaces: one for bang-style macros and one for attributes. When an attribute is resolved, any bang-style macros in scope will be ignored. And conversely resolving a bang-style macro will ignore attribute macros in scope. This prevents one style from shadowing another.

For example, the cfg attribute and the cfg macro are two different entities with the same name in the macro namespace, but they can still be used in their respective context.

It is still an error for a use import to shadow another macro, regardless of their sub-namespaces.

1

rustc currently warns about shadowing when using the same name for a label and lifetime in the same scope, but it still treats them independently. This is intended as a future-compatibility warning about a possible extension to the language. See PR #24162.