This question is predicated on the assumption that a friendly/ergonomic API in rust should prefer a reference to a type Q where T: Borrow<Q> instead of expecting &T directly. In my experience working with the API of other collection types like HashMap, this definitely seems to be the case. That said...
How come the binary_search method on Vec<T> is not defined that way? Currently, on stable, the binary_search implementation is as follows:
pub fn binary_search(&self, x: &T) -> Result<usize, usize> where T: Ord, { self.binary_search_by(|p| p.cmp(x)) } It seems like the following would be a better implementation:
pub fn binary_search_modified<Q>(&self, x: &Q) -> Result<usize, usize> where T: Borrow<Q>, Q: Ord + ?Sized, { self.binary_search_by(|p| p.borrow().cmp(x)) } A comparison of the two APIs above:
let mut v: Vec<String> = Vec::new(); v.push("A".into()); v.push("B".into()); v.push("D".into()); let _ = v.binary_search("C"); // Compilation error! let _ = v.binary_search(&String::from("C")); // Fine allocate and convert it to the exact type, I guess let _ = v.binary_search_modified("C"); // Far nicer API, does the same thing let _ = v.binary_search_modified(&String::from("C")); // Backwards compatible As a more general question, what considerations go into deciding if a method should accept &T or &Q ... where T: Borrow<Q>?