module - 返回私有项目的私有内部模块给出“公共接口中的私有类型”错误
问题描述
在下面的示例中,模块outer
具有私有类型Private
和私有内部模块inner
。inner
能够访问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
笏。由于以下几个原因,这对我来说是违反直觉的:
- 即使前面的代码定义了一个带有 Rust 认为“泄漏”的接口的函数,它也不会产生错误。该错误仅在
outer
尝试使用此功能时发生。 - 唯一
inner
可能“泄漏”的地方Private
是定义它的模块。
所以我的问题是:
- 这里到底发生了什么导致 Rust 断定该接口的任何部分都泄漏了?看起来好像
Private
它被定义在inner
. - 是否有一个完全合理的背景?我的第一个想法是这是编译器中的错误或隐私设计中的疏忽,但我怀疑情况是否如此。
- 有没有办法在不创建另一个模块的情况下解决这个问题?我相信我可以创建一个包装模块,然后在and中
Private
公开,但我不想这样做。outer
inner
解决方案
该函数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)
它来专门定位它。
推荐阅读
- node.js - 如何使用 pageToken?
- c++ - 如何在 C++ 控制台应用程序中绘制数字三角形?
- django - 验证唯一的电子邮件 django rest 框架序列化程序
- node.js - mongodb - 查询对象字段和数组字段
- typo3 - 如何迁移 config.persistence.classes 子类
- dialogflow-es - 在用户可能尝试传递多条信息的情况下,应该如何处理对话轮次?
- go - 如何在 Cassandra 中插入包含列表的表
- python - Robot Framework API - 使用一个类获取测试套件/子套件结果和测试用例结果
- reactjs - 如何将提取的用户 ID 放入 mern 堆栈的文本字段中
- java - Tomcat 9 配置文件位置