Limit a generic type to be either A or B

It's possible to do this with an enum and From/Into and a sealed trait.

pub struct Alpha;
pub struct Beta;

pub enum AlphaOrBeta {
    Alpha(Alpha),
    Beta(Beta),
}

impl From<Alpha> for AlphaOrBeta {
    fn from(alpha: Alpha) -> Self {
        Self::Alpha(alpha)
    }
}

impl From<Beta> for AlphaOrBeta {
    fn from(beta: Beta) -> Self {
        Self::Beta(beta)
    }
}

mod sealed {
    pub trait Sealed {}
    impl Sealed for super::Alpha {}
    impl Sealed for super::Beta {}
}

pub fn foo<T: Into<AlphaOrBeta> + sealed::Sealed>(x: T) {
    let x = x.into();
    // rest of code here
}

// foo(Alpha) and foo(Beta) both work in addition to passing the enum.
// Nothing else can work due to the sealed trait.
4 Likes