Documenting a public concrete variant of a private generic type

Viewed 82

In another question of mine, I asked how to publicly expose only a concrete variant (Foo<u32>) of a private generic type (Foo<T>). The suggested solution is as follows:

mod internal {
    /// Private documentation of `Foo`.
    pub struct Foo<X> {
        /// Private documentation of `x`.
        pub x: X,
    }

    impl Foo<u32> {
        pub fn foo() -> u32 {
            32
        }
    }

    impl Foo<u8> {
        pub fn foo() -> u8 {
            8
        }
    }
}

/// Public documentation of `FooBar`.
pub type FooBar = internal::Foo<u32>;

This works, in the sense that the public API just contains FooBar, but not Foo. However, it is lacking from a documentation point of view. Here's the output of cargo doc for FooBar:


Screenshot of Cargo documentation


As you can see,

  • The private type Foo appears in the documentation, but it's not a link and Foo gets no separate
  • Neither the private documentation of Foo, nor that of Foo.x is shown

As a result, this documentation is not really useful. Obviously I could add more information to the documentation of FooBar, but that still would not make the documentation of FooBar look like that of a regular struct.

With this approach, the documentation of FooBar is clearly inferior to the "equivalent" definition of FooBar like this:

/// Public documentation of `FooBar`.
pub struct FooBar {
    /// Public documentation of `x`.
    x: u32,
}

I've put "equivalent" into quotes because I do assume that from the compiler's point of view (and obviously that of cargo doc), these two definitions of FooBar are quite different. My issue is that readers of my documentation should not have to care about that difference.

Is there a way to achieve the "natural" documentation in this situation?

I'm happy to use a completely different approach for hiding the generic Foo definition if that's necessary.

1 Answers

You can use #[cfg(doc)] to fake the item:

#[cfg(not(doc))]
pub type FooBar = internal::Foo<u32>;
#[cfg(doc)]
/// Public documentation of `FooBar`.
pub struct FooBar {
    /// Public documentation of `x`.
    pub x: u32,
}

But this will hide all impls (unless you'll copy them too) and duplicate code. So, don't do that.

Related