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.