Re-exports
Let's start by explaining what are re-exports. To do so, we will use an example where we are
writing a library (named lib
) with some types dispatched in sub-modules:
#![allow(unused)] fn main() { pub mod sub_module1 { pub struct Foo; } pub mod sub_module2 { pub struct AnotherFoo; } }
Users can import them like this:
use lib::sub_module1::Foo;
use lib::sub_module2::AnotherFoo;
But what if you want the types to be available directly at the crate root or if we don't want the modules to be visible for users? That's where re-exports come in:
// `sub_module1` and `sub_module2` are not visible outside.
mod sub_module1 {
pub struct Foo;
}
mod sub_module2 {
pub struct AnotherFoo;
}
// We re-export both types:
pub use crate::sub_module1::Foo;
pub use crate::sub_module2::AnotherFoo;
And now users will be able to do:
use lib::{Foo, AnotherFoo};
And since both sub_module1
and sub_module2
are private, users won't be able to import them.
Now what's interesting is that the generated documentation for this crate will show both Foo
and
AnotherFoo
directly at the crate root, meaning they have been inlined. There are a few rules to
know whether or not a re-exported item will be inlined.
Inlining rules
If a public item comes from a private module, it will be inlined:
mod private_module {
pub struct Public;
}
pub mod public_mod {
// `Public` will inlined here since `private_module` is private.
pub use super::private_module::Public;
}
// `Public` will not be inlined here since `public_mod` is public.
pub use self::public_mod::Public;
Likewise, if an item inherits #[doc(hidden)]
from any of its ancestors, it will be inlined:
#[doc(hidden)]
pub mod public_mod {
pub struct Public;
}
// `Public` be inlined since its parent (`public_mod`) has `#[doc(hidden)]`.
pub use self::public_mod::Public;
If an item has #[doc(hidden)]
, it won't be inlined (nor visible in the generated documentation):
// This struct won't be visible.
#[doc(hidden)]
pub struct Hidden;
// This re-export won't be visible.
pub use self::Hidden as InlinedHidden;
The same applies on re-exports themselves: if you have multiple re-exports and some of them have
#[doc(hidden)]
, then these ones (and only these) won't appear in the documentation:
mod private_mod {
/// First
pub struct InPrivate;
}
/// Second
#[doc(hidden)]
pub use self::private_mod::InPrivate as Hidden;
/// Third
pub use self::Hidden as Visible;
In this case, InPrivate
will be inlined as Visible
. However, its documentation will be
First Third
and not First Second Third
because the re-export with Second
as documentation has
#[doc(hidden)]
, therefore, all its attributes are ignored.
Inlining with #[doc(inline)]
You can use the #[doc(inline)]
attribute if you want to force an item to be inlined:
pub mod public_mod {
pub struct Public;
}
#[doc(inline)]
pub use self::public_mod::Public;
With this code, even though public_mod::Public
is public and present in the documentation, the
Public
type will be present both at the crate root and in the public_mod
module.
Preventing inlining with #[doc(no_inline)]
On the opposite of the #[doc(inline)]
attribute, if you want to prevent an item from being
inlined, you can use #[doc(no_inline)]
:
mod private_mod {
pub struct Public;
}
#[doc(no_inline)]
pub use self::private_mod::Public;
In the generated documentation, you will see a re-export at the crate root and not the type directly.
Attributes
When an item is inlined, its doc comments and most of its attributes will be inlined along with it:
mod private_mod {
/// First
#[cfg(a)]
pub struct InPrivate;
/// Second
#[cfg(b)]
pub use self::InPrivate as Second;
}
/// Third
#[doc(inline)]
#[cfg(c)]
pub use self::private_mod::Second as Visible;
In this case, Visible
will have as documentation First Second Third
and will also have as cfg
:
#[cfg(a, b, c)]
.
Intra-doc links are resolved relative to where the doc comment is defined.
There are a few attributes which are not inlined though:
#[doc(alias="")]
#[doc(inline)]
#[doc(no_inline)]
#[doc(hidden)]
(because the re-export itself and its attributes are ignored).
All other attributes are inherited when inlined, so that the documentation matches the behavior if the inlined item was directly defined at the spot where it's shown.