Rustdoc and private super trait

I am not good at English. Sorry if there are any funny expressions.

I know the following things about Rust.

  • Traits cannot directly have private methods.
  • There is a private super trait (pattern?) as a workaround.

The code in this post end is a typical Private super trait pattern, but when I documented it by rustdoc, I found the following output.

Rustdoc output

pub trait SomeTrait: PrivateTrait {
    // Required method
    fn public_method(&self);
}

To the best of my knowledge, PrivateTrait is not worth showing to users of this crate.
So why isn't this omitted?

Typical Private super trait pattern code.

use private::PrivateTrait;

mod private {
    pub trait PrivateTrait {
        fn private_method(&self) {
            println!("Hello from private.");
        }
    }

    impl<T> PrivateTrait for T {
    }
}

pub trait SomeTrait: PrivateTrait {
    fn public_method(&self);
}

impl<T> SomeTrait for T {
    fn public_method(&self) {
        self.private_method();
    }
}

#[test]
fn test() {
    ().public_method();
}

The pattern is called "sealed trait", since having Self be bound by private trait makes it impossible to implement outside of your crate. For the same reason, hiding that trait bound is impossible, otherwise there's nothing to explain why your trait can't be implemented by your dependants.

5 Likes

Thanks for your reply.
But I still don't understand it.

I interpreted the above point to mean that other crate structures or trates cannot implement SomeTrait (I am very sorry if I interpreted it incorrectly due to my poor English skills).

However, the following code could be executed without problems.
Am I misunderstanding something?

use rust_test::SomeTrait;

fn main() {
    (TestStruct {}).public_method();
    ().public_method();
}

struct TestStruct {}
trait TestTrait: SomeTrait {}
impl<T> TestTrait for T {}

cargo.toml

[package]
name = "rust_user"
version = "0.1.0"
edition = "2021"

[dependencies]
# `rust_test` includes `SomeTrait`.
rust_test = { path = "../rust_test" }
1 Like

Thanks again for your reply.

The m1::m2::Hidden in the code you provided seems to be valid only in the m1 module. Therefore, it seems impossible to implement m1::Foo, which implements m1::m2::Hidden, outside of the m1 module. As a result, m1::Foo cannot be a pub, can it?
In fact, commenting out the "illegal" part of your code still results in an error.

On the other hand, private::PrivateTrait in my code is only valid within a crate, and I give its implementation to SomeTrait within the crate. So SomeTrait can be used outside the crate.

However, since PrivateTrait cannot even use its name outside the crate, I don't think anyone outside the crate would want to know that we are implementing it.

Yeah, I messed up the example a little. Hidden is supposed to be pub without qualifiers. That way it's allowed in public interface, but is unnameable.

1 Like

I have organized my thoughts.

  1. There is a Trait D, which is an extension of the private Trait B, in some crate.
  2. Try to implement D for a structure in a different crate.
  3. However, B is not documented.
    • In the case shown by HJVT, it may not work because of the constraints in B.
    • In the cases I have shown, it always works because B fits all the types.

In other words, the crate user does not know what will happen in the end because B is not documented?

Hmmm, I still feel that rustdoc needs to do something about this....