Czy „pub” ma wskazywać publiczne na skrzynkę lub publiczne na moduł? [duplikować]

Dec 15 2020

Aby upublicznić metody z modułu podrzędnego, musisz jawnie wyeksportować je ponownie lub upublicznić sam moduł podrzędny:

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

Wydaje się, że pubjest to wskazówka, która jest używana do wskazania, że ​​rzecz powinna być publiczna tylko dla modułu (ponieważ możesz tego nie robić)

Ale jeśli używasz typu prywatnego zdefiniowanego w kontekście zewnętrznym, pojawi się błąd, jeśli spróbujesz ustawić publiczną funkcję obejmującą ją w kontekście wewnętrznym, nawet jeśli nie zostanie ponownie wyeksportowana.

mod foo {
    struct Foo;

    mod bar {
        use super::Foo;

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

prowadzi do

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

Jaki jest idiomatyczny sposób użycia pubsłowa kluczowego? Czy powinien być zarezerwowany dla rzeczy, które są faktycznie publiczne, czy może być używany do modułów wewnętrznych?

Odpowiedzi

2 vallentin Dec 15 2020 at 04:06

Przyczyną niepowodzenia kompilacji Twojego przykładu jest ostatecznie to, że tak mówi RFC (136) . (Zobacz także numer 22261 )

Jakie ograniczenia dotyczą przedmiotów publicznych?

Zasady dotyczące różnego rodzaju pozycji publicznych są następujące:

  • Jeżeli jest to staticdeklaracja, to pozycje, do których odnosi się jej typ, muszą być jawne.
  • Jeśli jest to fndeklaracja, elementy, do których odwołuje się jej zakres cech, typy argumentów i zwracany typ, muszą być publiczne.
  • Jeśli jest to deklaracja structlub enum, pozycje, do których odnosi się jej zakres cech i typy jej pubpól, muszą być publiczne.
  • Jeżeli jest to typedeklaracja, pozycje, o których mowa w jej definicji, muszą być jawne.
  • Jeśli jest to traitdeklaracja, elementy, do których odwołuje się jej super-cechy, w granicach cechy parametrów jej typu oraz w sygnaturach jej metod (patrz fnprzypadek powyżej), muszą być publiczne.

Krótko mówiąc, baznie może być, pubponieważ ma argument, który jest typem prywatnym. Tak więc, jeśli bazjest pubto umożliwić rodzicom mod foodo reeksportu bazprzez robi pub use bar::baz;. Jest to oczywiście niedozwolone i to jest powód, dla którego przykład jako całość jest nielegalny.

Niektórzy wcześniej wspomnieli, że pub fn bazpowinno to być dozwolone i zamiast tego podawać błąd kompilacji w przypadku ponownego eksportu modułu nadrzędnego. Jednak wykrycie tego wymagałoby bardziej złożonej analizy statycznej, a ostatecznie nie zostało to zrobione, ponieważ dokument RFC zdefiniował, że jest to nielegalne.


pubokreśla, że ​​element jest dostępny dla modułu nadrzędnego. Jeśli wszyscy przodkowie modułów tak pub, to ten element jest eksportowany przez skrzynię jako całość.

Słowo kluczowe pubumożliwia dostęp do dowolnego modułu, funkcji lub struktury danych z wnętrza modułów zewnętrznych. Słowa pubkluczowego można również użyć w usedeklaracji, aby ponownie wyeksportować identyfikator z przestrzeni nazw.

- Dokumentacja rdzy

Przy założeniu, że przedmiot jest publiczny lub prywatny, Rust umożliwia dostęp do elementu w dwóch przypadkach:

  1. Jeśli element jest publiczny, to można uzyskać do niego dostęp z zewnątrz z jakiegoś modułu m, jeśli masz dostęp do wszystkich modułów nadrzędnych elementu z m. Potencjalnie możesz również nazwać element poprzez ponowne eksportowanie. Zobacz poniżej.
  2. Jeśli element jest prywatny, może uzyskać do niego dostęp bieżący moduł i jego elementy podrzędne.

- Odniesienie do rdzy - Widoczność i prywatność