module - 私有(private)内部模块返回私有(private)项给出 "private type in public interface"错误

标签 module interface rust private public

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

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 认为“泄漏”的接口(interface)的函数。只有当 outer 试图使用这个函数时才会发生错误。
  • inner 唯一可能“泄露”Private 的地方是定义它的模块

所以我的问题是:

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

最佳答案

函数not_really_public_interface 公共(public)的,因此它可以被任何 其他模块使用。但是 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 中的任何模块。或者,如果 super 模块有一个名字,例如my_mod,您可以使用 pub(in::my_mod) 专门针对它。

关于module - 私有(private)内部模块返回私有(private)项给出 "private type in public interface"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50753923/

相关文章:

rust - 使用 Serde 序列化值时如何执行额外的数据库查询?

rust - 如何在 Rust 中实现包装向量上的迭代器特征?

c - 检测 Linux 内核空间中的进程创建

r - 如何在响应式 R Shiny 应用程序中的模块之间引导数据流?

java - 为什么我的接口(interface)类型化对象不会执行接口(interface)中未声明的方法?

java - 更喜欢非成员非友元函数......在 Java 中?

collections - AutoMapper 和接口(interface)类型的集合

用于循环导入的 python 解决方法

haskell - 如何导出类型类?

rust - 是什么使得在 Rust 中需要函数指针类型的地方可以使用闭包类型?