Skip to content

PartialOrd interaction with existing Ord impl causes weird error #136

@lcnr

Description

@lcnr

The following snippet errors

use std::marker::PhantomData;
use derive_where::derive_where;

trait Interner {}
#[derive_where(PartialOrd, Ord, PartialEq, Eq; I: Interner, T)]
struct Foo<T, I>(T, PhantomData<I>);

with

error[E0277]: the trait bound `T: Ord` is not satisfied
 --> src/main.rs:5:1
  |
5 | #[derive_where(PartialOrd, Ord, PartialEq, Eq; I: Interner, T)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `T`
  |
note: required for `Foo<T, I>` to implement `Ord`
 --> src/main.rs:5:1
  |
5 | #[derive_where(PartialOrd, Ord, PartialEq, Eq; I: Interner, T)]
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
6 | struct Foo<T, I>(T, PhantomData<I>);
  |        ^^^^^^^^^
  = note: this error originates in the derive macro `::derive_where::DeriveWhere` (in Nightly builds, run with -Z macro-backtrace for more info)

This is as the PartialOrd impl ends up expanding to

impl<T, I> ::core::cmp::PartialOrd for Foo<T, I>
where
    I: Interner,
    T: ::core::cmp::PartialOrd,
{
    #[inline]
    fn partial_cmp(
        &self,
        __other: &Self,
    ) -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, __other))
    }
}

This feels surprising to me. It feels generally preferable to always duplicate the equality check in PartialOrd instead 🤔 encountered in https://github.com/rust-lang/rust/pull/150271/changes/4c598a80758e59b3a86f54ade6217cb92285cb16..19521d91a0898af7f256ce6d520d641e98547b21#r2717159656

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions