SerendipityEx

关注成长,记录生活

「Rust 2018」中的模块路径

Rust 2018 引入了一些新的模块系统功能,但它们最终简化了模块系统,使其更加清晰。

总结来说是以下几点:

  • 99% 的情况下不再需要 extern crate
  • crate 关键字指的是当前的箱子(crate)。
  • 绝对路径以包名称开头,其中关键字 crate 指的是当前包。
  • foo.rsfoo/ 子目录可以共存;将子模块放在子目录中时不再需要 mod.rs

super or self

在路径上使用关键字 superself ,可以在访问项时消除歧义和防止不必要的路径的硬编码。

fn function() {
    println!("called `function()`");
}

mod cool {
    pub fn function() {
        println!("called `cool::function()`");
    }
}

mod my {
    fn function() {
        println!("called `my::function()`");
    }
    
    mod cool {
        pub fn function() {
            println!("called `my:🆒:function()`");
        }
    }
    
    pub fn indirect_call() {
        // 从当前作用域访问所有名为 `function` 的函数!
        print!("called `my::indirect_call()`, that\n> ");
        
        // `self` 关键字表示当前的模块作用域—— `my`。
        // 调用 `self::function()` 和直接访问 `function()` 两者都得到相同的结果,
        // 因为他们表示相同的函数。
        self::function();
        function();
        
        // 我们也可以使用 `self` 来访问 `my` 内部的另一个模块:
        self:🆒:function();
        
        // `super` 关键字表示父级作用域(在 `my` 模块外面)。
        super::function();
        
        // 这将在 *crate* 作用域内绑定 `cool::function` 。
        // 在这个例子中,crate 作用域是最外面的作用域。
        {
            use cool::function as root_function;
            root_function();
        }
    }
}

fn main() {
    my::indirect_call();
}

示例来自《Rust By Example》

对路径的改变

Rust 2018 中,使用声明中的路径必须以包名称,crateselfsuper 开头。

// Rust 2015
// bar.rs
pub struct Bar;

// foo.rs
use bar::Bar;

pub struct Foo;

// main.rs
mod foo;
mod bar;

fn main() {}

上面的代码在 Rust 2018 中是编译不通过的,缺少包名称开头,需要加上crate

// Rust 2018
// bar.rs
pub struct Bar;

// foo.rs
use crate::bar::Bar;

pub struct Foo;

// main.rs
mod foo;
mod bar;

fn main() {}

Rust 2018 中,use 声明的路径和其他代码中的路径始终以相同的方式工作,无论是在顶级模块还是在任何子模块中。都可以使用当前模块的相对路径,外部包名开始的路径,或者以cratesuperself开头的路径。

Reference

https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html#path-clarity

Rust开发环境搭建