`pub`は、パブリックからクレートまたはパブリックからモジュールを示すことを意味しますか?[複製]

Dec 15 2020

サブモジュールのメソッドをパブリックにするには、メソッドを明示的に再エクスポートするか、サブモジュール自体をパブリックにする必要があります。

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キーワードを使用する慣用的な方法は何ですか?実際に公開されているもののために予約する必要がありますか、それとも内部モジュールに使用できますか?

回答

2 vallentin Dec 15 2020 at 04:06

あなたの例がコンパイルに失敗する理由は、最終的にはRFC(136)がそう言ったからです。(問題22261も参照してください)

パブリックアイテムにはどのような制限が適用されますか?

各種パブリックアイテムのルールは以下のとおりです。

  • static宣言の場合、そのタイプで参照されるアイテムはパブリックである必要があります。
  • fn宣言の場合、特性境界、引数の型、および戻り値の型で参照される項目はパブリックである必要があります。
  • それがstructorenum宣言である場合、その特性境界およびそのpubフィールドのタイプで参照される項目はパブリックでなければなりません。
  • type宣言の場合、その定義で参照されている項目は公開されている必要があります。
  • trait宣言の場合、スーパートレイト、型パラメーターのトレイト境界、およびメソッドのシグニチャー(fn上記のケースを参照)で参照されるアイテムはパブリックである必要があります。

つまり、プライベート型の引数があるため、baz許可されていませんpub。したがって、場合はbazあるpub、それは親を許すmod foo再輸出をbaz行うことでpub use bar::baz;。もちろんこれは許可されておらず、これが例全体が違法である理由です。

pub fn baz許可されるべきであり、代わりに親モジュールがそれを再エクスポートした場合にコンパイルエラーを与えるべきであると以前に述べた人もいます。ただし、これを検出するには、より複雑な静的分析が必要になり、RFCで違法と定義されているため、最終的には実行されていません。


pub親モジュールがアイテムにアクセスできることを指定します。すべてのモジュールの祖先がpubである場合、そのアイテムはクレート全体によってエクスポートされます。

キーワードpubは、外部モジュールの内部から任意のモジュール、関数、またはデータ構造にアクセスできるようにします。このpubキーワードはuse、名前空間から識別子を再エクスポートするための宣言で使用することもできます。

-錆のドキュメント

アイテムがパブリックまたはプライベートのいずれかであるという概念により、Rustは次の2つの場合にアイテムへのアクセスを許可します。

  1. アイテムがパブリックである場合、mからすべてのアイテムの祖先モジュールにアクセスできる場合は、モジュールmから外部からアクセスできます。また、再エクスポートを通じてアイテムに名前を付けることができる可能性もあります。下記参照。
  2. アイテムがプライベートの場合、現在のモジュールとその子孫がアクセスできます。

-錆リファレンス-可視性とプライバシー