Aska
Aska

Reputation: 63

Rust: is there a way to know that an arg is of some generic type, without caring about its inner type?

I know that I can use the TypeId to find out if an arg is of some specific type:

use std::any::{Any, TypeId};

fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
    TypeId::of::<String>() == TypeId::of::<T>()
}

but is there a way to know that an arg is of some generic type, without caring about the inner type?

For exapmle, can I somehow find out if an arg is a Vec<_>, without caring for the inner type?

use std::any::{Any, TypeId};

fn is_vec<T: ?Sized + Any>(_s: &T) -> bool {
    TypeId::of::<Vec<_>>() == TypeId::of::<T>() // This fails with error[E0282]: type annotations needed
}

I would like to know if this is possible in any way in Rust, not only using TypeId.

Upvotes: 0

Views: 620

Answers (2)

Aiden4
Aiden4

Reputation: 2654

There is a generalizable way to do this in stable rust, although it won't let you check if a dyn Any is a Vec<_>. instead, what I did was create a super trait of any with an impl for both Vec<T> and dyn Any. Code:

trait MyAny:Any{
    fn get_container(&self)->Container;
} 

impl<T:Any> MyAny for Vec<T>{
    fn get_container(&self)->Container{
        Vector
    }
}
impl MyAny for dyn Any{
    fn get_container(&self)->Container{
        Any
    }
}

with container being an enum defined as

#[derive(Clone,Copy,PartialEq,Eq)]
#[non_exhaustive]
enum Container{
    Vector,
    Any,
}

from there, defining an is_vec function is easy:

fn is_vec<T:MyAny + ?Sized>(s:&T)->bool{
    s.get_container() == Vector
}

Playground

Upvotes: 1

phimuemue
phimuemue

Reputation: 35983

Right now, no way to do this in stable Rust comes to my mind.

However, as you ask for any way, here's a thing using specialization on nightly rust:

#![feature(specialization)]

trait TIsVector {
    fn is_vector(&self) -> bool;
}

impl<T> TIsVector for T {
    default fn is_vector(&self) -> bool {
        false
    }
}

impl<T> TIsVector for Vec<T> {
    default fn is_vector(&self) -> bool {
        true
    }
}

fn main() {
    dbg!(1usize.is_vector());
    dbg!(true.is_vector());
    dbg!("sdf".is_vector());
    dbg!(vec![1,2,3].is_vector());
}

Upvotes: 0

Related Questions