Runtime specialization for compound types with lifetime

similar to the Runtime specialization when types are equal I want to typecast from one ndarray::ArrayBase to another.

ArrayBase<S, D> has two type parameters:

  • S: is the Data representation. S is likely to contain a lifetime i.e.: ArrayBase<ViewRepr<&f64>, _>
  • D: Is the dimensions of the array

I do not intend to cast the type of S only the type of D so there should not be any need for S: 'static only D: 'static right?

Also I need to cast both owned and borrowed versions of ArrayBase. I have tried a bunch of different ways to do this and this seems to me tho only possible solution:

fn cast_arr_to_ix1<S, D>(arr: ArrayBase<S, D>) -> Option<ArrayBase<S, Ix1>>
where
    S: RawData,
    D: 'static,
{
    if TypeId::of::<D>() == TypeId::of::<Ix1>() {
        let ptr = &*ManuallyDrop::new(arr) as *const ArrayBase<S, D> as *const ArrayBase<S, Ix1>;
        Some(unsafe { ptr::read(ptr) })
    } else {
        None
    }
}

fn cast_arr_ref_to_ix1<S, D>(arr: &ArrayBase<S, D>) -> Option<&ArrayBase<S, Ix1>>
where
    S: RawData,
    D: 'static,
{
    if TypeId::of::<D>() == TypeId::of::<Ix1>() {
        let ptr = arr as *const ArrayBase<S, D> as *const ArrayBase<S, Ix1>;
        Some(unsafe { ptr.as_ref().unwrap_unchecked() })
    } else {
        None
    }
}
  • Is this actually safe?
  • is there any better way to do this without constraining S: 'static (that would be worse than no runtime specialization)?

There's a hack to specialize types while ignoring the safety requirement of static lifetime, based on the fact that Rust specializes clone() of Copy types:

See the use of unlimited_transmute in mapv_into_any for ndarray specifically. See also PR 1283, which makes mapv_into_any() work for different underlying storage types. The PR was rejected ostensibly because it is a breaking change, but also because the maintainers thought the trait arithmetic was too complicated, although I (the author of the PR) believe it is sound.

With regard to the 'static bound, my understanding is that anything you want to get a TypeId on has to be 'static due to limitations of the runtime type system. However, note

Please be careful with that hack and don't advertise it without adding caveats, it may result in UB if you're probing for something that directly or indirectly depends on lifetimes.

2 Likes