这最好从内联模块开始解释。模块从 crate 根开始按层次结构排列。每个板条箱在脱糖后看起来都是这样的:
// root
pub mod a {
pub mod b {
pub const X: u8 = 1;
}
}
mod foo {
}
引用树中的项目非常简单:
-
::
“下降”一个级别
-
super::
“上升”一个层次
-
crate::
转到根级别
可供参考的例子X
:
-
a::b::X
从板条箱根部开始
-
crate::a::b::X
从板条箱中的任何地方
-
super::a::b::X
从模块内foo
-
b::X
从模块内a
mod foo;
实际上只是以下任一内容的语法糖:
#[path = "foo.rs"]
mod foo;
// or
#[path = "foo/mod.rs"]
mod foo;
进一步脱糖:
mod foo {
include!("foo.rs");
}
// or
mod foo {
include!("foo/mod.rs");
}
If foo.rs
(or foo/mod.rs
)包含一个mod bar;
那么整棵树看起来像:
mod foo {
mod bar {
// contents of `bar.rs` (or `foo/bar/mod.rs`)
}
// remaining contents of `foo.rs`
}
请注意,使用mod.rs
虽然仍受支持,但不鼓励。相反,建议使用foo.rs
for crate::foo
并放置任何子模块foo
in the foo/
目录。
If both src/foo/mod.rs
and src/foo.rs
存在的话,编译器会抛出如下错误:
error[E0761]: file for module `foo` found at both "src\foo.rs" and "src\foo\mod.rs"
--> src\main.rs:1:1
|
1 | mod foo;
| ^^^^^^^^
|
= help: delete or rename one of them to remove the ambiguity
crate::
总是对应于当时正在编译的包的根模块。如果您的板条箱足够复杂或不遵循惯例,那么某些crate::...
项目路径可以引用不同文件中的不同内容。但通过遵循约定可以轻松避免混淆。
以下是我用来避免混淆的约定列表:
- avoid
#[path]
属性
- 总是使用
src/foo.rs
代替src/foo/mod.rs
- 如果您有多个根模块(例如库和二进制板条箱),它们都应该直接位于
src
- 最小化花哨的配置
Cargo.toml
,尽可能使用默认值