What's the deal with `pub extern crate`?

Reading the documentation for @hannobraun's Stepper library, I see several pub extern crate declarations. I've never seen a visibility modifier on extern crate before, and the reference doesn't say anything about such usage. Does pub extern crate foo; have the same effect as extern crate foo; followed by pub use foo::*; (or just the second one in edition 2018 I guess)? Can you use other visibility modifiers with extern crate? Where is all this documented, if anywhere?

1 Like

It's equivalent to this:

pub use embedded_hal;
pub use embedded_time;
pub use ramp_maker;

It allows you to access the contents of those crates as stepper::embedded_hal::the_thing

2 Likes

Thanks, that seems reasonable. I wonder whether this being allowed is an artifact of the pre-2018 system where extern crate was essential.

It seems like the reference could use a paragraph about which items can take a visibility qualifier, and what it means in each case.

I don't know whether pub extern is an artifact of earlier times, or where this usage is documented. It's just something I picked up over my many years of using Rust.

As @alice notes, this could be replaced with pub use. I prefer pub extern crate in this case, as I think it makes it a bit clearer that external dependencies are being re-exported here. But given that this topic exists, I'm probably wrong about what is obvious and what isn't :slight_smile:

As for the motivation, I like to re-export all dependencies of a library that are also directly relevant to the user. This saves the user from having to specify those dependencies themselves, and especially from having to keep the dependency versions in sync over time (which can get annoying). I consider this a best practice, but I don't know if anyone else agrees.

2 Likes

Thanks for the explanation! That motivation for the re-exports makes sense to me.

As long as one is familiar with extern crate already I don't think it's particularly obscure -- the declarations appear under "Re-exports" in the rustdocs, so it's just a matter of figuring out what the re-exported paths are. (And that's not hard to figure out with some experimentation, which I didn't do here only because I'm lazy.) I could see it being confusing for someone who only knows post-2018 Rust, though.

Every type of item except macro items can take a visibility qualifier (reference).

The visibility qualifiers always have the same meaning: A private item creates a name that is visible within its parent module (including within its submodules). Adding pub makes the same name visible everywhere that its parent module is visible. Adding pub(...) further restricts visibility to the specified ancestor module.

1 Like

Thanks, this settles my confusion.

I missed this because I was looking only in the "Extern crates" and "Visibility and Privacy" subsections; I think the latter could use a sentence like what you've written here (unless I missed something equivalent while skimming it).

This makes sense and is indeed covered in the reference. I guess I was just thrown by the unfamiliar usage and didn't follow the reasoning to its logical conclusion.

Yeah, it should probably just become pub use. I'd be happy to accept a pull request to that effect (or I'll do it myself at some point).