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.