重新导出

让我们首先解释什么是重新导出。为此,我们将使用一个示例,其中我们正在编写一个库(名为 lib),其中一些类型在子模块中分发

#![allow(unused)]
fn main() {
pub mod sub_module1 {
    pub struct Foo;
}
pub mod sub_module2 {
    pub struct AnotherFoo;
}
}

用户可以像这样导入它们

use lib::sub_module1::Foo;
use lib::sub_module2::AnotherFoo;

但是,如果您希望类型直接在 crate 根目录可用,或者我们不希望模块对用户可见怎么办?这就是重新导出发挥作用的地方

// `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;

现在用户将能够做到

use lib::{Foo, AnotherFoo};

由于 sub_module1sub_module2 都是私有的,因此用户将无法导入它们。

现在有趣的是,为这个 crate 生成的文档将直接在 crate 根目录显示 FooAnotherFoo,这意味着它们已被内联。有一些规则需要知道重新导出的项目是否会被内联。

内联规则

如果公共项目来自私有模块,它将被内联

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;

同样,如果项目从其任何祖先继承 #[doc(hidden)],它将被内联

#[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;

如果项目具有 #[doc(hidden)],它将不会被内联(也不会在生成的文档中可见)

// This struct won't be visible.
#[doc(hidden)]
pub struct Hidden;

// This re-export won't be visible.
pub use self::Hidden as InlinedHidden;

同样适用于重新导出本身:如果您有多个重新导出,其中一些具有 #[doc(hidden)],那么这些(并且只有这些)将不会出现在文档中

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;

在这种情况下,InPrivate 将被内联为 Visible。但是,它的文档将是 First Third 而不是 First Second Third,因为具有 Second 作为文档的重新导出具有 #[doc(hidden)],因此,它的所有属性都被忽略。

使用 #[doc(inline)] 内联

如果您想强制内联项目,可以使用 #[doc(inline)] 属性

pub mod public_mod {
    pub struct Public;
}
#[doc(inline)]
pub use self::public_mod::Public;

使用此代码,即使 public_mod::Public 是公共的并且存在于文档中,Public 类型也将同时存在于 crate 根目录和 public_mod 模块中。

使用 #[doc(no_inline)] 阻止内联

#[doc(inline)] 属性相反,如果您想阻止内联项目,可以使用 #[doc(no_inline)]

mod private_mod {
    pub struct Public;
}
#[doc(no_inline)]
pub use self::private_mod::Public;

在生成的文档中,您将在 crate 根目录看到一个重新导出,而不是直接看到类型。

属性

当项目被内联时,它的文档注释和大多数属性将与它一起被内联

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;

在这种情况下,Visible 将具有 First Second Third 作为文档,并且还将具有 cfg#[cfg(a, b, c)]

文档内链接 相对于定义文档注释的位置解析。

但是,有一些属性不会被内联

  • #[doc(alias="")]
  • #[doc(inline)]
  • #[doc(no_inline)]
  • #[doc(hidden)](因为重新导出本身及其属性被忽略)。

所有其他属性在内联时都会被继承,以便文档与内联项目直接定义在显示它的位置的行为相匹配。

这些规则也适用于使用 glob 重新导出内联项目的情况

mod private_mod {
    /// First
    #[cfg(a)]
    pub struct InPrivate;
}

#[cfg(c)]
pub use self::private_mod::*;

否则,显示的属性将来自重新导出的项目,而重新导出本身的属性将被忽略

mod private_mod {
    /// First
    #[cfg(a)]
    pub struct InPrivate;
}

#[cfg(c)]
pub use self::private_mod::InPrivate;

在上述情况下,cfg(c) 不会在文档中显示。