首页 > 解决方案 > 返回私有项目的私有内部模块给出“公共接口中的私有类型”错误

问题描述

在下面的示例中,模块outer具有私有类型Private和私有内部模块innerinner能够访问Private(因为子模块可以访问其父级的私有项目,即使它们没有作为公共停放)。

inner定义一个函数not_really_public_interface()。虽然它被标记为公开,但它实际上只可供使用,outer因为inner它本身不是公开的。

外部.rs

struct Private;
mod inner {
  use super::Private;
  pub fn not_really_public_interface() -> Private {
    Private
  }
}

这编译没有任何问题。

outer应该可以inner::not_really_public_interface()用来获取Private,只要确保不导出即可。所以让我们这样做:

pub fn main() {
  let _ = self::inner::not_really_public_interface();
}

正确的?

标准错误

error[E0446]: private type `Private` in public interface
 --> src/outer.rs:4:3
  |
4 | /   pub fn not_really_public_interface() -> Private {
5 | |     Private
6 | |   }
  | |___^ can't leak private type

笏。由于以下几个原因,这对我来说是违反直觉的:

所以我的问题是:

标签: moduleinterfacerustprivatepublic

解决方案


该函数not_really_public_interface 公共的,因此它可以被任何其他模块使用。但是该Private结构只能由您的根和inner模块访问。

如果导入了另一个模块,就会发生泄漏not_really_public_interface。Rust 抱怨这可能会发生,因为它在本地报告错误,而不是对所有模块和 crate 中的所有用法采取“全局”视图。最终,这种方法对人类来说更容易预测,对机器来说也更快。

Rust 可以让你更精确地控制可见性。如果您告诉它该功能仅对上一级的模块(super模块)可用,那么它知道没有泄漏的可能性:

mod inner {
    use super::Private;

    pub(super) fn not_really_public_interface() -> Private { Private }
}

您也可以使用crate代替super, 来表示同一个 crate 中的任何模块。或者,如果超级模块有一个名称,例如my_mod,您可以使用pub(in ::my_mod)它来专门定位它。


推荐阅读