繁体   English   中英

Rust 带有通配符使用声明的子模块行为

[英]Rust Submodule Behavior with Wildcard Use Declarations

我试图了解使用通配符路径时(子)模块导入是如何工作的。 我能想到的最简单的演示如下,其中两个模块,或者可能是两个 crate,共享相同的模块结构。

pub mod primary {
    pub mod a {
        pub mod b {
            pub struct A(pub i32);
        }
    }
}

pub mod import {
    pub use crate::primary::*;
    // Compiles and executes fine with this commented out, but fails with
    // "error[E0433]: failed to resolve: could not find `b` in `a`"
    // otherwise. The error refers to the usage in the assert_eq macro
    // pub mod a {}
}

fn main() {
    assert_eq!(import::a::b::A(42).0, 42);
}

我的一般想法是,由于第一种情况,在pub mod a {}被注释掉的情况下,通配符应该将通配符拾取的所有子模块扩展到它正在扩展的路径中的子模块中。 不是这样吗? 如果是这样,思考的适当方式是什么?

使用声明对此没有太多详细信息。

*一起use会导入所有名称,除了那些与当前模块中已经存在的名称冲突的名称。

相比:

pub mod primary {
    pub fn f() {
        println!("p::f");
    }
}

pub mod import {
    pub use crate::primary::*;
}

fn main() {
    import::f();
}

p::f打印

pub mod primary {
    pub fn f() {
        println!("p::f");
    }
}

pub mod import {
    pub use crate::primary::*;

    pub fn f() {
        println!("import::f");
    }
}

fn main() {
    import::f();
}

打印import::f


这对于函数和常量来说似乎很明显(否则它会使*非常有限,上游库不可能在不冒破坏下游用户的情况下添加任何项目),但对于模块来说似乎更加混乱。 您必须记住,您不能多次定义一个模块(即“重新打开”一个模块)。 以下是非法的:

pub mod primary {
    pub mod a {}
    pub mod a {}
}

失败了

error[E0428]: the name `a` is defined multiple times
 --> src/lib.rs:3:5
  |
2 |     pub mod a {}
  |     --------- previous definition of the module `a` here
3 |     pub mod a {}
  |     ^^^^^^^^^ `a` redefined here
  |
  = note: `a` must be defined only once in the type namespace of this module

您可以通过再添加一个级别来解决这种特殊情况:

pub mod primary {
    pub mod a {
        pub mod b {
            pub struct A(pub i32);
        }
    }
}

pub mod import {
    pub mod a {
        pub use crate::primary::a::*;
    }
}

fn main() {
    assert_eq!(import::a::b::A(42).0, 42);
}

通配符导入为模块顶层的所有项目创建别名。

在您的示例中,由于primary仅包含一个项目a ,因此通配符导入创建了一个别名import::a ,它引用模块primary::a

每当发生冲突时,明确命名的项目的优先级高于通过通配符导入的项目。 实际上,您可以通过声明一个新项目或通过从另一个模块按名称导入它来隐藏通配符导入。

每个mod声明声明一个不同的模块。 模块中碰巧具有相同名称或别名的项目没有隐式合并。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM