ideasman42
ideasman42

Reputation: 47968

How to reference private types from public functions in private modules?

I want to group similar functions in a file. Those functions need to return a type which is not public:

struct MyStruct;

mod my_mod {
    use super::MyStruct;

    // There are other, similar functions that also return `MyStruct`
    pub fn foo() -> MyStruct {
        MyStruct
    }
}

fn main() {
    let _var = my_mod::foo();
}

This fails with the error

error[E0446]: private type `MyStruct` in public interface
 --> src/main.rs:7:3
  |
1 |     struct MyStruct;
  |     - `MyStruct` declared as private
...
7 |         pub fn foo() -> MyStruct { MyStruct }
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type

In general, it makes sense not to allow public functions to have private types in their signature, but in this specific case the structure is available at the modules root level.

Is there a way to support this without making MyStruct public?

Upvotes: 7

Views: 2696

Answers (2)

Gabe Nodarse
Gabe Nodarse

Reputation: 344

I encountered this same problem. Rust 2018 seems to have solved it; just refer to the submodule's "public" function as pub(crate), AKA pub(crate) fn foo().

This makes the function only public to the crate: https://doc.rust-lang.org/nightly/edition-guide/rust-2018/module-system/more-visibility-modifiers.html

Upvotes: 1

Francis Gagné
Francis Gagné

Reputation: 65692

I have a feeling that this error is unwarranted. It should only be an error if my_mod is pub or if the functions are re-exported in an outer scope.

That said, I found a workaround: move MyStruct to a sibling module and make MyStruct pub, but not the module.

use types::MyStruct;

mod types {
    pub struct MyStruct;
}

mod my_mod {
    use super::MyStruct;

    pub fn foo() -> MyStruct {
        MyStruct
    }
}

fn main() {
    let _var = my_mod::foo();
}

Upvotes: 8

Related Questions