命名空间
命名空间是声明的名称的逻辑分组。名称根据名称所指代的实体类型被隔离到不同的命名空间中。命名空间允许一个命名空间中的名称不会与另一个命名空间中的相同名称冲突。
在一个命名空间内,名称以层次结构的形式组织,层次结构的每一级都有自己的命名实体集合。
有几个不同的命名空间,每个命名空间包含不同类型的实体。名称的使用将根据上下文在不同的命名空间中查找该名称的声明,如名称解析章节所述。
以下是命名空间列表及其对应的实体
- 类型命名空间
- 值命名空间
- 宏命名空间
- 生命周期命名空间
- 标签命名空间
不同命名空间中重叠名称如何被明确使用的一个示例
#![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
项目本身不属于特定的命名空间。相反,它可以根据被导入的项目类型将别名引入多个命名空间。
子命名空间
宏命名空间被分成两个子命名空间:一个用于感叹号风格宏,另一个用于属性。当解析属性时,作用域内的任何感叹号风格宏都将被忽略。反之,解析感叹号风格宏将忽略作用域内的属性宏。这可以防止一种风格遮蔽另一种风格。
例如,cfg
属性和cfg
宏是宏命名空间中具有相同名称的两个不同实体,但它们仍然可以在各自的上下文中使用。
对于use
导入来说,遮蔽另一个宏仍然是一个错误,无论它们的子命名空间是什么。