返回私有项目的私有内部模块给出“公共接口中的私有类型”错误

问题描述 投票:0回答:2

在下面的示例中,模块

outer
有一个私有类型
Private
和一个私有内部模块
inner
inner
能够访问
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
    定义它的模块
  • 所以我的问题是:

到底发生了什么事情导致 Rust 得出此接口的任何部分存在泄漏的结论?看起来它对待
    Private
  • 就好像它是在
    Private
    中定义的一样。
    是否有一个上下文可以让这句话完全有意义?我的第一个想法是这是编译器中的错误或隐私设计中的疏忽,但我怀疑情况确实如此。
  • 有没有办法在不创建另一个模块的情况下解决这个问题?我相信我可以创建一个包装器模块,然后在
  • inner
  • Private
    中公开
    outer
    ,但我不想这样做。
    
        
module interface rust private public
2个回答
11
投票
inner

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

如果导入另一个模块,就会发生泄漏

inner

。 Rust 抱怨这种“可能”发生,因为它在本地报告错误,而不是对所有模块和板条箱中的所有用法采取“全局”视图。最终,这种方法对于人类来说推理起来更具可预测性,对于机器来说速度更快。


Rust 可以让你更精确地控制可见性。如果你告诉它该函数可用于上一级模块(

not_really_public_interface

模块),那么它就知道不存在泄漏的可能性: super


您还可以使用

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

,来表示同一个 crate 中的任何模块。或者,如果超级模块有一个名称,例如

super
,您可以使用
my_mod
来专门针对它。
    
在我的例子中,一个更简单的解决方案是将 

pub(in ::my_mod)

0
投票
pub

    

© www.soinside.com 2019 - 2024. All rights reserved.