string icon indicating copy to clipboard operation
string copied to clipboard

Implement `PartialEq`, `PartialOrd` and `Ord` via the dereferenced `str`

Open tesaguri opened this issue 5 years ago • 0 comments

The documentation of Borrow says that Eq, Ord and Hash implementation of a type which implements Borrow<T> must behave identical to T. On the other hand, String<T> implements those traits with #[derive], which does not necessarily comply with that contract.

In particular, the following test (code adapted from the documentation of Borrow) should pass, which currently fails.

#[derive(Debug)]
struct CaseInsensitiveStr<'a>(&'a str);
impl<'a> AsRef<[u8]> for CaseInsensitiveStr<'a> {
    fn as_ref(&self) -> &[u8] {
        self.0.as_bytes()
    }
}
unsafe impl<'a> StableAsRef for CaseInsensitiveStr<'a> {}

impl<'a> PartialEq for CaseInsensitiveStr<'a> {
    fn eq(&self, other: &Self) -> bool {
        self.0.eq_ignore_ascii_case(&other.0)
    }
}
impl<'a> Eq for CaseInsensitiveStr<'a> {}

let s = CaseInsensitiveStr("hello");
let t = CaseInsensitiveStr("HELLO");

assert_eq!(s, t);

let s = String::try_from(s).unwrap();
let t = String::try_from(t).unwrap();
assert_ne!(s, t);
assert_ne!(Borrow::<str>::borrow(&s), Borrow::<str>::borrow(&t));

In addition, current implementations (since 56d15f97629da6b45ad73311ed7b6a36c1464ed4?) can violate Hash trait's contract (k1 == k2 -> hash(k1) == hash(k2)) depending on the underlying type.

tesaguri avatar Nov 19 '20 17:11 tesaguri