Expand description

#[sealed]

MSRV 1.51.0

This crate provides a convenient and simple way to implement the sealed trait pattern, as described in the Rust API Guidelines [1].

[dependencies]
sealed = "0.4"

Example

In the following code structs A and B implement the sealed trait T, the C struct, which is not sealed, will error during compilation.

You can see a demo in demo/.

#[sealed]
trait T {}

pub struct A;
#[sealed]
impl T for A {}

pub struct B;
#[sealed]
impl T for B {}

pub struct C;
impl T for C {} // compile error

Details

The attribute generates a private uniquely named module when attached to a trait definition, when attached to an impl block the generated code simply implements the sealed trait for the respective type.

// #[sealed]
// trait T {}
trait T: __seal_t::Sealed {}
mod __seal_t {
    pub trait Sealed {}
}

pub struct A;

// #[sealed]
// impl T for A {}
impl T for A {}
impl __seal_t::Sealed for A {}

Arguments

The expanded code may be customized with the following attribute arguments.

erase

Turns on trait bounds erasure. This is useful when using the #[sealed] attribute inside a function. By default, all the bounds are propagated to the generated Sealed trait.

// #[sealed(erase)]
// trait Trait<T: ?Sized + Default> {}
trait Trait<T: ?Sized + Default>: __seal_trait::Sealed<T> {}
mod __seal_trait {
    pub trait Sealed<T> {}
}

pub(crate) or pub(in some::path)

Allows to tune visibility of the generated sealing module (the default one is private). This useful when the trait and its impls are defined in different modules.

mod lets {
    pub mod attempt {
        pub mod some {
            pub mod nesting {
                #[sealed(pub(in super::super::super::super))]
                pub trait T {}
            }
        }
    }
}

pub struct A;
#[sealed]
impl lets::attempt::some::nesting::T for A {}

Notice, that just pub is disallowed as breaks the whole idea of sealing.

#[sealed(pub)] // compile error
trait T {}

pub struct A;
#[sealed]
impl T for A {}

Attribute Macros