【问题标题】:Private inner module returning private item gives "private type in public interface" error返回私有项目的私有内部模块给出“公共接口中的私有类型”错误
【发布时间】:2018-11-18 02:50:15
【问题描述】:

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

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

outer.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

Wat. 这对我来说是违反直觉的,原因如下:

  • 即使前面的代码定义了一个带有 Rust 认为“泄漏”的接口的函数,它也不会产生错误。该错误仅在outer 尝试使用此功能时发生。
  • inner 唯一可能“泄露”Private 的地方是定义它的模块

所以我的问题是:

  • 到底发生了什么导致 Rust 断定该接口的任何部分都泄漏了?似乎它将Private 视为在inner 中定义。
  • 是否存在完全合理的上下文?我的第一个想法是这是编译器中的错误或隐私设计中的疏忽,但我怀疑情况是否如此。
  • 有没有办法在不创建另一个模块的情况下解决这个问题?我相信我可以创建一个包装模块,然后在outerinner 中公开Private,但我不想这样做。

【问题讨论】:

  • 当我尝试编译您建议的代码时,即使不使用 not_really_public_interface 我也会遇到同样的错误。这是playground

标签: module interface rust private public


【解决方案1】:

函数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,表示同一个板条箱中的任何模块。或者,如果超级模块有名称,例如my_mod,您可以使用pub(in ::my_mod) 专门针对它。

【讨论】:

    猜你喜欢
    • 2019-09-13
    • 2014-01-01
    • 2014-11-20
    • 2015-12-27
    • 2014-01-03
    • 2014-06-03
    • 2018-11-09
    相关资源
    最近更新 更多