简体   繁体   English

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

[英]Rust Submodule Behavior with Wildcard Use Declarations

I was trying to understand how (sub)module imports work when using wildcard paths.我试图了解使用通配符路径时(子)模块导入是如何工作的。 The simplest demonstration I could come up with is as follows, where two modules, or perhaps two crates, share the same module structure.我能想到的最简单的演示如下,其中两个模块,或者可能是两个 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);
}

My general thought, was, since the first case, where the pub mod a {} is commented out works, the wildcard should expand all submodules the wildcard picks up into submodules in the path in which it is expanding.我的一般想法是,由于第一种情况,在pub mod a {}被注释掉的情况下,通配符应该将通配符拾取的所有子模块扩展到它正在扩展的路径中的子模块中。 Is this not the case?不是这样吗? If so, what's the appropriate way to think about?如果是这样,思考的适当方式是什么?

TheUse declarations doesn't have a lot of detail on this. 使用声明对此没有太多详细信息。

use with a * imports all the names, except for those that would conflict with names that already exist in the current module.*一起use会导入所有名称,除了那些与当前模块中已经存在的名称冲突的名称。

Compare:相比:

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

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

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

which prints p::f top::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();
}

which prints import::f . 打印import::f


This might seem obvious for functions and constants (it would otherwise make * very limited, making it impossible for upstream libraries to add any item without risking to break downstream users), but it might seem more confusing for modules.这对于函数和常量来说似乎很明显(否则它会使*非常有限,上游库不可能在不冒破坏下游用户的情况下添加任何项目),但对于模块来说似乎更加混乱。 You have to remember though that you can't define a module multiple times (ie. "reopen" a module).您必须记住,您不能多次定义一个模块(即“重新打开”一个模块)。 The following is illegal:以下是非法的:

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

and fails with失败了

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

You can solve this particular case by adding one more level:您可以通过再添加一个级别来解决这种特殊情况:

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);
}

A wildcard import creates aliases to all items on the top level of the module.通配符导入为模块顶层的所有项目创建别名。

In your example, since primary contains only one item, a , the wildcard import creates an alias import::a , which refers to the module primary::a .在您的示例中,由于primary仅包含一个项目a ,因此通配符导入创建了一个别名import::a ,它引用模块primary::a

Whenever conflicts arise, explicitly named items are given higher precedence than items that were imported via a wildcard.每当发生冲突时,明确命名的项目的优先级高于通过通配符导入的项目。 Effectively, you can shadow a wildcard import by declaring a new item or by importing it by name from another module.实际上,您可以通过声明一个新项目或通过从另一个模块按名称导入它来隐藏通配符导入。

Each mod declaration declares a different module.每个mod声明声明一个不同的模块。 There is no implicit merging of items in modules that happen to have the same name or alias.模块中碰巧具有相同名称或别名的项目没有隐式合并。

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

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