命名空间
命名空间是声明的名称的逻辑分组。名称根据其引用的实体类型被分成不同的命名空间。命名空间允许一个命名空间中的名称出现与另一个命名空间中的同名名称不冲突。
有几个不同的命名空间,每个包含不同类型的实体。名称的使用将根据上下文在不同的命名空间中查找该名称的声明,如名称解析章节中所述。
以下是命名空间列表及其对应的实体:
- 类型命名空间
- 值命名空间
- 宏命名空间
- 生命周期命名空间
- 标签命名空间
不同命名空间中重叠名称可以无歧义使用的示例:
#![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;
}
}
}
没有命名空间的命名实体
以下实体具有显式名称,但名称不是任何特定命名空间的一部分。
字段
尽管结构体、枚举和联合体字段有名称,但命名字段不存在于显式命名空间中。它们只能通过字段表达式访问,该表达式只检查被访问的特定类型的字段名称。
Use 声明
Use 声明具有它导入到作用域中的命名别名,但 use 项本身不属于特定命名空间。相反,它可以根据被导入的项类型将别名引入多个命名空间。
子命名空间
宏命名空间分为两个子命名空间:一个用于叹号式宏,一个用于属性。当解析属性时,将忽略作用域中的任何叹号式宏。反之,解析叹号式宏将忽略作用域中的属性宏。这防止了一种样式遮蔽另一种样式。
例如,[cfg 属性]和 [cfg 宏]是宏命名空间中具有相同名称的两个不同实体,但它们仍然可以在各自的上下文中使用。
Note
use导入仍然不能在模块或块中创建同名的重复绑定,无论子命名空间如何。#[macro_export] macro_rules! mymac { () => {}; } use myattr::mymac; // error[E0252]: the name `mymac` is defined multiple times.