【问题标题】:Is `pub` meant to indicate public-to-crate or public-to-module? [duplicate]`pub` 是指 public-to-crate 还是 public-to-module? [复制]
【发布时间】:2021-03-25 12:43:46
【问题描述】:

要将子模块中的方法公开,您必须明确地重新导出它们,否则将子模块本身公开:

mod foo {
    mod bar {
        pub fn baz() {}
    }
    pub use self::bar::baz;
}

这似乎暗示pub 用于指示事物应该只对模块公开(因为您可以选择不这样做)

但是,如果您使用在外部上下文中定义的私有类型,如果您尝试在内部上下文中将涉及它的公共函数设为公共,即使它没有重新导出,也会出现错误。

mod foo {
    struct Foo;

    mod bar {
        use super::Foo;

        pub fn baz(foo: Foo) {}
    }
}

结果

error[E0446]: private type `Foo` in public interface
 --> src/lib.rs:7:9
  |
2 |     struct Foo;
  |     - `Foo` declared as private
...
7 |         pub fn baz(foo: Foo) {}
  |         ^^^^^^^^^^^^^^^^^^^^ can't leak private type

使用pub 关键字的惯用方式是什么?它应该保留给实际上公开的东西还是可以用于内部模块?

【问题讨论】:

标签: rust visibility conventions


【解决方案1】:

您的示例无法编译的原因最终是因为RFC (136) 是这样说的。 (另见issue 22261

哪些限制适用于公共项目?

各类公共物品的规则如下:

  • 如果是static 声明,则其类型中引用的项目必须是公共的。
  • 如果是fn 声明,则在其特征边界、参数类型和返回类型中引用的项必须是公共的。
  • 如果是structenum 声明,则在其特征边界和pub 字段类型中引用的项目必须是公共的。
  • 如果是type 声明,则其定义中引用的项目必须是公开的。
  • 如果它是 trait 声明,则在其超特征、其类型参数的特征边界和其方法的签名中引用的项目(请参阅上面的 fn 案例)必须是公共的。

简而言之,baz 不允许为pub,因为它有一个私有类型的参数。因此,如果bazpub,它将允许父mod foo 通过执行pub use bar::baz; 重新导出baz。这当然是不允许的,这也是整个例子非法的原因。

之前有人提到应该允许pub fn baz,而是在父模块重新导出它的情况下给出编译错误。然而,这将需要更复杂的静态分析来检测,并且最终没有完成,因为 RFC 定义它是非法的。


pub 指定项目可由父模块访问。如果所有模块祖先都是pub,则该项目将由 crate 作为一个整体导出。

关键字pub 使任何模块、函数或数据结构都可以从外部模块内部访问。 pub 关键字也可以在 use 声明中使用,以从命名空间重新导出标识符。

——Rust Documentation

鉴于项目是公共的或私有的,Rust 允许在两种情况下访问项目:

  1. 如果一个项目是公共的,那么如果您可以从 m 访问该项目的所有祖先模块,则可以从某个模块 m 外部访问它。您还可以通过再导出来命名该项目。见下文。
  2. 如果一个项目是私有的,它可以被当前模块及其后代访问。

——The Rust Reference - Visibility and Privacy

【讨论】:

  • 我了解 如何 pub 的运作机制。我很困惑什么时候应该使用它。为什么编译器在我的示例中抱怨 private-type-in​​-public-interface?
  • 请注意,我用conventions标记了这个问题
  • 好吧,给我一分钟,我会重做答案:)
猜你喜欢
  • 2017-02-10
  • 2015-08-19
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-10
  • 2022-12-26
相关资源
最近更新 更多