Rc uses visibly behavior-changing specialization: is that okay?

It looks like you can do this with any trait actually. Unfortunately, it seems you can only check if the type implements such trait, but you may not use it (because Copy and Eq have no methods).

struct IsDebug<'a, T> {
    is_debug: &'a Cell<bool>,
    _marker: PhantomData<T>,
}

impl<T> Clone for IsDebug<'_, T> {
    fn clone(&self) -> Self {
        self.is_debug.set(false);
        IsDebug {
            is_debug: self.is_debug,
            _marker: PhantomData,
        }
    }
}
impl<T: Debug> Copy for IsDebug<'_, T> {}

fn is_it_though<T>() -> bool {
    let is_debug = Cell::new(true);
    let _ = [IsDebug::<T> {
        is_debug: &is_debug,
        _marker: PhantomData,
    }]
    .clone();
    is_debug.get()
}
struct Foo; 
println!("i32: {}", is_it_though::<i32>()); 
println!("Foo: {}", is_it_though::<Foo>());

prints:

i32: true
Foo: false

If Copy and Eq weren't mere marker traits they could leak specialization features in stable.

7 Likes