The reason your example fails to compile, is ultimately because the RFC (136) said so. (See also issue 22261)
What restrictions apply to public items?
The rules for various kinds of public items are as follows:
- If it is a
static
declaration, items referred to in its type must be public.
- If it is an
fn
declaration, items referred to in its trait bounds, argument types, and return type must be public.
- If it is a
struct
or enum
declaration, items referred to in its trait bounds and in the types of its pub
fields must be public.
- If it is a
type
declaration, items referred to in its definition must be public.
- If it is a
trait
declaration, items referred to in its super-traits, in the trait bounds of its type parameters, and in the signatures of its methods (see fn
case above) must be public.
In short, baz
is not allowed to be pub
because it has an argument which is a private type. Thus, if baz
is pub
it would allow the parent mod foo
to re-export baz
by doing pub use bar::baz;
. This is of course not allowed, and this is the reason why the example as a whole is illegal.
Some have previously mentioned that pub fn baz
should be allowed, and instead to give a compile error in the event that the parent module re-exports it. However, that would require more complex static analysis to detect, and ultimately has not been done because the RFC defined that it is illegal.
pub
specifies that the item is accessible by the parent module. If all module ancestors are pub
, then that item is exported by the crate as a whole.
The keyword pub
makes any module, function, or data structure accessible from inside of external modules. The pub
keyword may also be used in a use
declaration to re-export an identifier from a namespace.
– Rust Documentation
With the notion of an item being either public or private, Rust allows item accesses in two cases:
- If an item is public, then it can be accessed externally from some module m if you can access all the item's ancestor modules from m. You can also potentially be able to name the item through re-exports. See below.
- If an item is private, it may be accessed by the current module and its descendants.
– The Rust Reference - Visibility and Privacy