Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 243
ideasman42 Avatar asked Sep 05 '16 16:09

ideasman42


People also ask

What is pub mod?

The mod keyword is used to declare submodules. We need to explicitly declare functions, structs etc as public so they can be consumed in other modules. The pub keyword makes things public. The use keyword is used to shorten the module path. We don't need to explicitly declare 3rd party modules.

What is pub crate?

pub(crate) makes an item visible within the current crate. pub(super) makes an item visible to the parent module. This is equivalent to pub(in super) . pub(self) makes an item visible to the current module. This is equivalent to pub(in self) or not using pub at all.

What is super in Rust?

// The `super` keyword refers to the parent scope (outside the `my` module).

How do you make a public function in Rust?

Modules in Rust are private by default. On the contrary, functions in a public module can be accessed by other modules. Modules should be prefixed with pub keyword to make it public.


1 Answers

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();
}
like image 88
Francis Gagné Avatar answered Nov 15 '22 07:11

Francis Gagné