Hacker News new | ask | show | jobs
by rspeer 3399 days ago
I seem to run into functions that require String instead of &str all the time, most recently the "assert_eq!" macro which -- maybe I'm not understanding it correctly -- refuses to compare a &str to a String.

Can you tell me how I would remove the excessive uses of ".to_string()" from the tests in this module? https://github.com/rspeer/rust-nlp-tools/blob/master/languag...

1 comments

  fn main() {
      let s1 = "Hello, world"; // &str
      let s2 = String::from("Hello, world"); // String
      
      assert_eq!(s1, s2);
      assert_eq!(s2, s1);
  }
compiles just fine for me?
Okay, once again I try to find an example from my code, and once again it turns out that Rust makes it simple in the simple case, but the more complex cases are still confusing.

If I change the test value Some("zh".to_string()) into Some("zh"), it points to that line and tells me:

    expected struct `std::string::String`, found &str
Sure, it's a different situation because the value is wrapped in an Option. But if String and &str are truly compatible, I would never expect to see that error message.
Ah yes. So this is an area where the diagnostic is _slightly_ misleading; it's trying to point out that you have two different types, and that that's the difference between the two of them. It's not that they can't be compared. Maybe a bug should be filed...

String and &str can normally be compared because of Deref, that is, &String derefs to &str. Option, on the other hand, does not implement Deref, and so no coercion happens. Rust doesn't do a lot of coercions, but Deref is one of the bigger ones.

Back to the _actual_ topic at hand, I can see how this can be a pain point until you know the rules, though. :/

> String and &str can normally be compared because of Deref, that is, &String derefs to &str. Option, on the other hand, does not implement Deref, and so no coercion happens.

For this particular case, any particular reason we couldn't add an impl of PartialEq? In fact, once we have specialization, couldn't we have a general impl of PartialEq for Options of Deref types?

  impl<T> PartialEq<Option<T>> for Option<T> where T: PartialEq<T>
does exist, but I'm not 100% sure why Deref doesn't kick in here, I just know that it doesn't.

> couldn't we have a general impl of PartialEq for Options of Deref types?

I think the issue is None. You'd get a null pointer, which doesn't make any sense in safe rust.

> I think the issue is None. You'd get a null pointer, which doesn't make any sense in safe rust.

No, I don't mean an impl between Option<T> and T, I mean a bidirectional impl of PartialEq between Option<T> and Option<U> where U is T's Deref::Target.

In that case, None doesn't cause an issue; None == None, and Some(t) == Some(u) iff *t == u