Так что я сейчас использую
rustc 1.36.0-nightly (8dd4aae9a 2019-05-04)
и в своем lib.rs я включил
#! [Feature (specialization)]
А в модуле моей библиотеки я имею следующее, которое не компилируется.Насколько я понимаю, он должен компилироваться, даже без specialization
, но это не так - в любом случае.
use std::hash::{Hash,Hasher};
#[derive(Debug, Copy, Clone,PartialEq,Eq)]
struct HashKey<T>(T);
//default
impl<T : Hash> Hash for HashKey<T> {
fn hash<H>(&self, state: &mut H)
where H : Hasher
{
self.0.hash(state)
}
}
impl Hash for HashKey<f32> {
fn hash<H>(&self, state: &mut H)
where H : Hasher
{
unsafe { std::mem::transmute::<f32,u32>(self.0) }.hash(state)
}
}
impl Hash for HashKey<f64> {
fn hash<H>(&self, state: &mut H)
where H : Hasher
{
unsafe { std::mem::transmute::<f64,u64>(self.0) }.hash(state)
}
}
Как мы все знаем, f32
, а также f64
не являются ни Eq
, ниHash
из-за проблемы NaN
, как обсуждалось, например, в этого вопроса .Использование небезопасного reinterpret_cast<u32>
обходного пути, так как меня не волнует Nan
в моем случае.
Итак, у меня есть признак хэша черты для любого HashKey<T> where T : Hash
, и у меня есть значения как для f32
, так и дляf64
, которые, как указано, не Hash
.Таким образом, это даже не специализация, так как эти 3 имплиса охватывают ортогональных случая.
Несмотря на всю эту замечательную логику, я получаю ошибку:
conflicting implementations of trait `std::hash::Hash` for type `naive::HashKey<f32>`:
conflicting implementation for `naive::HashKey<f32>`
note: upstream crates may add new impl of trait `std::hash::Hash` for type `f32` in future versionsrustc(E0119)
naive.rs(10, 1): first implementation here
naive.rs(18, 1): conflicting implementation for `naive::HashKey<f32>`
, котораяприводит к вопросам:
Я что-то не так делаю?Как это сделать правильно?Почему это проблема в первую очередь, учитывая, что эти ссылки относятся к наборам типов без перекрытия?