在下面的例子中,模块outer
有一个私有(private)类型Private
和一个私有(private)内部模块inner
。 inner
能够访问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
中定义。 - 是否存在完全合理的上下文?我的第一个想法是这是编译器中的错误或隐私设计中的疏忽,但我怀疑是这种情况。
- 有没有办法在不创建另一个模块的情况下解决这个问题?我相信我可以创建一个包装器模块,然后在
outer
和inner
中将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/