Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What purpose does a public module serve when one or more functions need to be public for this to have any effect?

Tags:

rust

What purpose does pub in front of a module declaration in Rust serve?

All the members of a module are private by default, irrespective of whether a module is public or private (the default).

In order for a member of a module to be public, that entity (function, etc) must be declared public using pub also.

Hence it appears that the scope (public or private) of a module is redundant. Is this the case?

Reference: https://doc.rust-lang.org/book/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html

like image 266
FreelanceConsultant Avatar asked Oct 16 '25 01:10

FreelanceConsultant


2 Answers

This question makes perfect sense if it's coming from someone who mostly writes applications. There isn't much difference.

But I write libraries for a living (not in Rust unfortunately, but the same considerations apply), so the difference matters a lot to me.

Let's say I have a crate Foo and it has two modules, creatively named Bar and Baz, and each one has public function f and private function g but Baz is private:

pub mod Bar {
  pub fn f() -> () {}
  fn g() -> () {}
}

mod Baz {
  pub fn f() -> () {}
  fn g() -> () {}
}

So in this setup:

  • Bar::g and Baz::g are local to their respective modules, I can't e.g. call them in main.
  • Bar::f and Baz::f are public in their modules, I can e.g. call them from main.
  • Bar::f is public to consumers of my crate (i.e. is part of my public API), they can call Foo::Bar::f, but crucially not Foo::Baz::f.

That last bit is the important part, and if you don't regularly work on libraries intended for other developers (or even intended for yourself to use in multiple projects) it's an easy distinction to miss.

like image 59
Jared Smith Avatar answered Oct 18 '25 15:10

Jared Smith


This allows you to have a fine-grained scopes of encapsulation. Consider the following example.

pub mod A {
    mod B {
        pub fn foo() {
            println!("foo");
        }
    }
    
    pub fn bar() {
        println!("calling foo");
        B::foo()
    }
}

fn main() {
    A::bar();
    
    // A::B is private. Can't call foo
    // A::B::foo();
}

You have a public module A and inside of it you have a private module B with helper functions. Functions in A can call functions from B, but callers outside of A cannot call its helper functions.

like image 21
Aleksander Krauze Avatar answered Oct 18 '25 14:10

Aleksander Krauze