“External code” here means code outside the module where the pub use appears. In the example from the book, that module in the root module of a library crate, so pub makes this path visible in other crates that use this library.
Without this re-export, other crates could not access the hosting module, because it would be available only within the private front_of_house module.
At a very high level import is comparable to use (no pub) but export has no single direct Rust analog. The reason is that Rust has pub use which is all at the same time an import and a re-export of that imported item. But there are also privacy controls on modules, functions, types etc., e.g. the pub in pub fn foo() {} which also have a strong effect on what's being exported from a module.
Javascript's export more or less can do both of those things so in that sense it's more flexible.
Which brings me to the fact that rust is oriented around the module concept which by definition consists of one or more files AFAIK, vs the resource-oriented nature of Javascript imports and exports (which does have finer controls on what is imported, of course).
These discussions about Rust modules and use always confuse the socks of me.
For example: As far as I can tell use does not import anything in Rust. All it does is provide a shorter way of referring to something that is already available. I can use `use' like this:
use pcg::Pcg;
...
let mut pcg = Pcg::default();
But I don't need use to import what I want, I could just use it as is:
let mut pcg = pcg::Pcg::default();
I conclude the actual importing has been done by Cargo.toml.
This is very different to what goes on with 'import' in JS or 'require' in node.js.
Similarly it looks to me as if pub use in Rust is not exporting anything either. It's only making a different way of referencing something that is already available.
mod public {
mod private {
pub const ZERO: u8 = 0;
}
pub use private::ZERO;
}
fn main() {
// works; but would not work without `pub use` in `mod public`
println!("{}", public::ZERO);
// error[E0603]: module `private` is private
// println!("{}", public::private::ZERO);
}
Once could make everything public, then no pub use is required:
pub mod public {
pub mod private {
pub const ZERO: u8 = 0;
}
}
fn main() {
println!("{}", public::private::ZERO);
}
I'm just not sure I would call any of this "importing" or "exporting" in the JS sense. It's all very different. As I said, always confuses the socks off me.
@PaulRBerg
The first is exporting symbols.
The second is privacy control: deciding what's accessible from outside the JS module/resource, and what is not, and it takes the shape of deciding what to export.
Well what is an import? Regardless of how it's actually implemented (and indeed there are a fair amount of differences between JS and Rust in that matter), conceptually it can be seen as making a symbol defined externally to the current module directly accessible from that same current module. In that sense, it's an import. A similar reasoning holds for re-exporting with pub use.
Technically crates are not linked when they are not used in the code, even when they are defined as dependency in Cargo.toml. Most of the time this doesn't matter, but sometimes a crate for example exports an unmangled symbol. In that case you may need to use use my_crate; without referring to my_crate later on just to link my_crate. As another example bevy_dylib contains a use bevy_internal; line to ensure that all bevy crates are linked into libbevy_dylib.so. bevy then contains a #[cfg(feature = "dynamic")] use bevy_dylib; to dynamically link to libbevy_dylib.so when the "dynamic" feature is enabled. This means that all crates of bevy will be dynamically linked, thereby significantly reducing the time necessary to link the final executable.