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

Cha*_*er5 1 module private interface public rust

在下面的示例中,模块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
  }
}
Run Code Online (Sandbox Code Playgroud)

这编译没有任何问题.

outer应该能够用来inner::not_really_public_interface()获取Private,只要它确保不输出它.所以我们这样做:

pub fn main() {
  let _ = self::inner::not_really_public_interface();
}
Run Code Online (Sandbox Code Playgroud)

对?

标准错误

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
Run Code Online (Sandbox Code Playgroud)

笏.由于以下几个原因,这对我来说是违反直觉的:

  • 前一代码没有产生错误,即使它定义了一个带有Rust认为"泄漏"的接口的函数.只有在outer尝试使用此功能时才会出现此错误.
  • inner可能"泄漏" 的唯一地方Private定义它的模块.

所以我的问题是:

  • 究竟是什么导致Rust得出结论该接口的任何部分泄漏?看起来好像它Private被定义为inner.
  • 是否存在完全合理的背景?我的第一个想法是,这是编译器中的错误或隐私设计中的疏忽,但我怀疑是这种情况.
  • 有没有办法在不创建另一个模块的情况下解决这个问题?我相信我可以创建一个包装模块,然后只是让Private公众中outerinner,但我不想这样做.

Pet*_*all 6

该功能not_really_public_interface 公共的,因此可以被任何其他模块使用.但Private结构只能由您的根和inner模块访问.

如果导入另一个模块,则会发生泄漏not_really_public_interface.Rust抱怨说这可能发生,因为它在本地报告错误,而不是在所有模块和板条箱中的所有用法中采用"全世界"视图.最终,这种方法对于人类来说更容易预测并且对于机器来说更快.

Rust可让您更精确地控制可见性.如果你告诉它该功能对模块提供一级(super模块),那么它就知道不存在泄漏的可能性:

mod inner {
    use super::Private;

    pub(super) fn not_really_public_interface() -> Private { Private }
}
Run Code Online (Sandbox Code Playgroud)

您也可以使用crate代替super,表示同一个箱子中的任何模块.或者,如果超级模块有名称,例如my_mod,您可以使用pub(in ::my_mod)它来专门定位它.