well..
you're right.
A safe way exists in my neat example:
#![feature(min_specialization)]
use std::fmt::Debug;
struct Spec<T:Debug,U:Debug>(T,U);
impl<T:Debug,U:Debug> Spec<T,U>{
fn byref(&self){println!("(T={:?},U={:?}),byref",self.0,self.1)}
fn bymut(&mut self){println!("(T={:?},U={:?}),bymut",self.0,self.1)}
fn bytake(self)->(T,U){println!("(T={:?},U={:?}),take and drop",self.0,self.1);(self.0,self.1)}
}
#[repr(transparent)]
struct Wrapper<const SEQ:usize,T>(T);
trait SpecSpec<T,U>{
fn show_spec();
fn ref_spec(&self){}
fn mut_spec(&mut self){}
fn take_spec(self)->(T,U) where Self: Sized{unimplemented!("We must implement take for every specific type.")}
}
trait WrapperSpec<T,U> where Self: Sized{
fn show_spec(){}
fn ref_spec(self){}
fn mut_spec(mut self){}
fn take_spec(self)->(T,U){unimplemented!("We must implement take for every specific type.")}
}
// first default level, could be overwrite.
impl<T:Debug,U:Debug> WrapperSpec<T,U> for Wrapper<0,Spec<T,U>>{
fn show_spec(){println!("neither T({}) nor U({}) is the specialization version",std::any::type_name::<T>(),std::any::type_name::<U>())}
fn take_spec(self)->(T,U){self.0.bytake()}
}
impl<T:Debug,U:Debug> WrapperSpec<T,U> for Wrapper<0,&Spec<T,U>>{
fn ref_spec(self)where Self: Sized{self.0.byref()}
}
impl<T:Debug,U:Debug> WrapperSpec<T,U> for Wrapper<0,&mut Spec<T,U>>{
fn mut_spec(mut self)where Self: Sized{self.0.bymut()}
}
// second default level, using default impl to enable the further modification.
impl<T:Debug,U:Debug,G> WrapperSpec<T,U> for Wrapper<1,G> where Wrapper<0,G>:WrapperSpec<T,U>{
default fn show_spec(){Wrapper::<0,G>::show_spec()}
default fn ref_spec(self){Wrapper::<0,G>::ref_spec(Wrapper(self.0))}
default fn mut_spec(mut self){Wrapper::<0,G>::mut_spec(Wrapper(self.0))}
default fn take_spec(self)->(T,U){Wrapper::<0,G>::take_spec(Wrapper(self.0))}
}
impl<U:Debug,G> WrapperSpec<i16,U> for Wrapper<1,G> where Wrapper<0,G>:WrapperSpec<i16,U>{
fn show_spec(){println!("T({}) is the specialization version, but U({}) is not.",std::any::type_name::<i16>(),std::any::type_name::<U>())}
}
// second default level, using default impl to enable the further modification.
impl<T:Debug,U:Debug,G> WrapperSpec<T,U> for Wrapper<2,G> where Wrapper<1,G>:WrapperSpec<T,U>{
default fn show_spec(){Wrapper::<1,G>::show_spec()}
default fn ref_spec(self){Wrapper::<1,G>::ref_spec(Wrapper(self.0))}
default fn mut_spec(mut self){Wrapper::<1,G>::mut_spec(Wrapper(self.0))}
default fn take_spec(self)->(T,U){Wrapper::<1,G>::take_spec(Wrapper(self.0))}
}
impl<T:Debug,G> WrapperSpec<T,i32> for Wrapper<2,G> where Wrapper<1,G>:WrapperSpec<T,i32>{
fn show_spec(){println!("U({}) is the specialization version, but T({}) is not.",std::any::type_name::<i32>(),std::any::type_name::<T>())}
} // no conflict here, even if we do not provide a SpecSpec<i16,i32> type.
// second default level, using default impl to enable the further modification.
impl<T:Debug,U:Debug,G> WrapperSpec<T,U> for Wrapper<3,G> where Wrapper<2,G>:WrapperSpec<T,U>{
default fn show_spec(){Wrapper::<2,G>::show_spec()}
default fn ref_spec(self){Wrapper::<2,G>::ref_spec(Wrapper(self.0))}
default fn mut_spec(mut self){Wrapper::<2,G>::mut_spec(Wrapper(self.0))}
default fn take_spec(self)->(T,U){Wrapper::<2,G>::take_spec(Wrapper(self.0))}
}
impl<G> WrapperSpec<i16,i32> for Wrapper<3,G> where Wrapper<2,G>:WrapperSpec<i16,i32>{
fn show_spec(){println!("both T and U have a specialization version, we need to specific them.")}
} // no conflict here, even if we do not provide a SpecSpec<i16,i32> type.
// second default level, using default impl to enable the further modification.
impl<T:Debug,U:Debug,G> WrapperSpec<T,U> for Wrapper<4,G> where Wrapper<3,G>:WrapperSpec<T,U>{
default fn show_spec(){Wrapper::<3,G>::show_spec()}
default fn ref_spec(self){Wrapper::<3,G>::ref_spec(Wrapper(self.0))}
default fn mut_spec(mut self){Wrapper::<3,G>::mut_spec(Wrapper(self.0))}
default fn take_spec(self)->(T,U){Wrapper::<3,G>::take_spec(Wrapper(self.0))}
}
impl<G> WrapperSpec<i32,i16> for Wrapper<4,G> where Wrapper<3,G>:WrapperSpec<i32,i16>{
fn show_spec(){println!("Although there is no specialization version, but we do concern about that.")}
}
impl<T:Debug,U:Debug> SpecSpec<T,U> for Spec<T,U> where Wrapper<4,Spec<T,U>>:WrapperSpec<T,U>{
fn show_spec(){<Wrapper<4,Spec<T,U>>>::show_spec()}
fn ref_spec(&self){<Wrapper<4,&Spec<T,U>>>::ref_spec(Wrapper(self))}
fn mut_spec(&mut self){<Wrapper<4,&mut Spec<T,U>>>::mut_spec(Wrapper(self))}
fn take_spec(self)->(T,U){<Wrapper<4,Spec<T,U>>>::take_spec(Wrapper(self))}
}
impl<T:Debug,U:Debug> Spec<T,U> where Spec<T,U>:SpecSpec<T,U>{
fn check(mut self){
Spec::<T,U>::show_spec();
self.ref_spec();
self.mut_spec();
println!(" take returns {:?}",self.take_spec());
}
}
fn main(){
Spec(1i8,2i8).check();
Spec(3i16,4i8).check();
Spec(5i8,6i32).check();
Spec(7i16,8i32).check();
Spec(9i32,10i16).check();
}