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