How to restrict in derived traits?

Consider the following code:

trait ToUsize {
    fn to_usize(&self) -> Option<usize>;
}

enum InnerType {
    UInt64,
    Float64,
}

trait Inner: 'static {}

impl Inner for u64 {}
impl Inner for f64 {}

trait ArrayType {
    type Inner: Inner;
    const TYPE: InnerType;
}

struct ArrayTypeU64 {}
impl ArrayType for ArrayTypeU64 {
    type Inner = u64;
    const TYPE: InnerType = InnerType::UInt64;
}

struct ArrayTypeFloat64 {}
impl ArrayType for ArrayTypeFloat64 {
    type Inner = f64;
    const TYPE: InnerType = InnerType::Float64;
}

trait UsizableArray: ArrayType {}

impl UsizableArray for ArrayTypeU64 {}

fn to_usize<K: UsizableArray>(array: Vec<K>) -> Option<Vec<usize>>
where K::Inner: ToUsize {
    // convert array into `Vec<usize>` via to_usize if all items can
    // be converted to `usize` via `ToUsize::to_usize()`
    todo!()
}

fn main() {}

In this example, I restricted K::Inner to ToUsize. Is there a way of restricting this in the trait declaration, i.e. "UsizableArray::Inner must always be ToUsize".

Something like

trait UsizableArray: ArrayType where ArrayType::Inner: ToUsize {}

In other words, is it possible to restrict the type when declaring derived traits?

I haven’t checked it, but I think this would work:

trait UsizableArray: ArrayType where <Self as ArrayType>::Inner: ToUsize {}
1 Like

Thanks a lot for the suggestion.

That almost works: it continues to require all implementations to have a where, which is what I was trying to avoid in the first place.

I.e. this does not compile:


trait ToUsize {
    fn to_usize(&self) -> Option<usize>;
}

enum InnerType {
    UInt64,
    Float64,
}

trait Inner: 'static + Copy {}

impl Inner for u64 {}
impl Inner for f64 {}

impl ToUsize for u64 {
    fn to_usize(&self) -> Option<usize> {
        Some(*self as usize)
    }
}

trait ArrayType {
    type Inner: Inner;
    const TYPE: InnerType;
}

struct ArrayTypeU64 {}
impl ArrayType for ArrayTypeU64 {
    type Inner = u64;
    const TYPE: InnerType = InnerType::UInt64;
}

struct ArrayTypeFloat64 {}
impl ArrayType for ArrayTypeFloat64 {
    type Inner = f64;
    const TYPE: InnerType = InnerType::Float64;
}

trait UsizableArray: ArrayType where <Self as ArrayType>::Inner: ToUsize {}

impl UsizableArray for ArrayTypeU64 {}

fn to_usize<K: UsizableArray>(array: Vec<K>) -> Option<Vec<usize>> {
    // convert array into `Vec<usize>` via to_usize if all items can
    // be converted to `usize` via `num::FromPrimitive::from()`
    todo!()
}

fn main() {}