Skip to content

Implement PartialOrd<str> for String, PartialOrd<[T]> for Vec<T> #232

@ecton

Description

@ecton

Proposal

Problem statement

Currently, String and str implement PartialEq for each other, but do not
implement PartialOrd for each other. This is also true of Vec<T> and [T].
I want to submit a pull request adding implementations for PartialOrd to round
out the trait implementations of these types.

Motivating examples or use cases

When working on a sorted vec implementation, I originally implemented get()
lookups using PartialOrd<SearchType>. In effect, it looked like this:

struct Map<Key, Value>(Vec<(Key, Value)>);

impl<Key, Value> Map<Key, Value> {
    fn get<SearchKey>(&self, key: &SearchKey) -> Option<&Value>
    where
        Key: PartialOrd<SearchKey>,
        SearchKey: ?Sized,
    {
        todo!()
    }
}

fn main() {
    let map = Map(vec![(String::from("a"), ())]);
    map.get("a");
}

This does not compile, however, due this missing implementation.

I then looked at other standard library types that have Borrow implementations
that I'm aware of: OsString/OsStr and PathBuf/Path. Both implement
PartialOrd in addition to PartialEq.

Solution sketch

In alloc, add these implementation blocks:

// PartialOrd for String with str
impl PartialOrd<str> for String {}
impl<'a> PartialOrd<&'a str> for String {}
impl<'a> PartialOrd<Cow<'a, str>> for String {}

// PartialOrd for str with String
impl PartialOrd<String> for str {}
impl<'a> PartialOrd<&'a String> for str {}
impl<'a> PartialOrd<Cow<'a, str>> for str {}

// PartialOrd for Vec<T,A> with [T]
impl<T, U, A> PartialOrd<[U]> for Vec<T, A> where T: PartialOrd<U>, A: Allocator {}
impl<'a, T, U, A> PartialOrd<&'a [U]> for Vec<T, A> where T: PartialOrd<U>, A: Allocator  {}

// PartialOrd for Vec<T,A> with [T; N]
impl<T, U, A, const N: usize> PartialOrd<[U; N]> for Vec<T, A> where T: PartialOrd<U>, A: Allocator {}
impl<'a, T, U, A, const N: usize> PartialOrd<&'a [U; N]> for Vec<T, A> where T: PartialOrd<U>, A: Allocator  {}

// PartialOrd for [T] with Vec<U, A>
impl<T, U, A> PartialOrd<Vec<U,A>> for [T]  where T: PartialOrd<U>, A: Allocator {}
impl<'a, T, U, A> PartialOrd<&'a Vec<U, A>> for [T] where T: PartialOrd<U>, A: Allocator  {}

// PartialOrd for [T; N] with Vec<U, A>
impl<T, U, A, const N: usize> PartialOrd<Vec<U,A>> for [T; N]  where T: PartialOrd<U>, A: Allocator {}
impl<'a, T, U, A, const N: usize> PartialOrd<&'a Vec<U, A>> for [T; N] where T: PartialOrd<U>, A: Allocator  {}
impl<'a, T, U, A, const N: usize> PartialOrd<Cow<'a, U>> for [T; N] where T: PartialOrd<U>, A: Allocator  {}

This list of proposed implementations was gathered by looking at the PartialEq
list of String/Vec and adding the missing PartialOrd implementations. The
implementations for these blocks should be similar to their PartialEq
equivalents, but calling cmp/partial_cmp instead of eq.

Alternatives

Because of foreign trait implementation rules, the main workaround is to either
use a newtype wrapper that implements these traits or introduce new
traits
that serve the same purpose as PartialOrd.

Links and related work

This is my first API change proposal. I feel like this is a fairly straightforward change, to the best of my knowledge, due to foreign trait implementation rules preventing these additional implementations from being breaking changes. I personally cannot think of a reason that these shouldn't be added, but I am new to std lib development, so I may not be aware of ways that these implementations could cause issues in the ecosystem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ACP-acceptedAPI Change Proposal is accepted (seconded with no objections)T-libs-apiapi-change-proposalA proposal to add or alter unstable APIs in the standard libraries

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions