Skip to content

1.100 beta crater regression: Behavior change with #[derive(Ord)] and manual impl PartialOrd #164141

Description

@theemathas

This regression was discovered in the 1.100 beta crater run.

[INFO] [stdout] ---- poker_utils::test::test_get_best_hand stdout ----
[INFO] [stdout] 
[INFO] [stdout] thread 'poker_utils::test::test_get_best_hand' (387) panicked at src/poker_utils.rs:119:9:
[INFO] [stdout] assertion `left == right` failed
[INFO] [stdout]   left: HighCard(A, Q, 7, 3, 2)
[INFO] [stdout]  right: HighCard(A, Q, 9, 8, 7)

https://crater-reports.s3.amazonaws.com/beta-1.100-4/1.100.0-beta.1/gh/aprowe.equity-cli/log.txt

Possibly relevant code: https://github.com/aprowe/equity-cli/blob/481a9d0d48d7fd651c1afa667cd3ce210b3ac30d/src/poker_hand.rs#L63

Activity

  1. added
    C-bugCategory: This is a bug.
    E-needs-bisectionCall for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc
    E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
    on Oct 11, 2026
  2. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Oct 11, 2026
  3. theemathas commented on Oct 11, 2026

    @theemathas
    ContributorAuthor

    Probably one of the builtin macros changes did something. cc @cyrgani

  4. asquared31415 commented on Oct 11, 2026

    @asquared31415
    Contributor

    Ord specifically says to not combine derives and manual impl, and there's even a clippy lint for this.

    Because Ord implies a stronger ordering relationship than PartialOrd, and both Ord and PartialOrd must agree, you must choose how to implement Ord first. You can choose to derive it, or implement it manually. If you derive it, you should derive all four traits. If you implement it manually, you should manually implement all four traits, based on the implementation of Ord.

    It's likely that Vec::iter().map().max() got some new specialization that's using the derived Ord instead of the PartialOrd impl.

  5. theemathas commented on Oct 11, 2026

    @theemathas
    ContributorAuthor

    I did a bisection and you're right.


    searched toolchains 2fb4ed81d6a3131a5ba6d75fa1aeb15bc998a5f6 through fd98695850065878fa7de48808dca4f0901cefbb
    
    
    ********************************************************************************
    Regression in c9b7f178899788fac53d942b82cf97665ee59aaa
    ********************************************************************************
    
    Attempting to search unrolled perf builds
    Found commits ["9aa503aa", "369655d3", "02a976f5", "d3bf528c", "33c5df03"]
    installing 9aa503aa0d7d67f132376e5425174a869a273ace
    rust-std-nightly-x86_64-unknown-linux-gnu: 31.31 MB / 31.31 MB [========================================================] 100.00 % 11.32 MB/s testing...
    RESULT: 9aa503aa0d7d67f132376e5425174a869a273ace, ===> Compile error
    uninstalling 9aa503aa0d7d67f132376e5425174a869a273ace
    
    Regression in https://github.com/rust-lang/rust/commit/9aa503aa0d7d67f132376e5425174a869a273ace. Note that if it is a legacy rollup build, it might be available in https://github.com/rust-lang-ci/rust/commit/9aa503aa0d7d67f132376e5425174a869a273ace.
    The PR introducing the regression in this rollup is #160203: `Iterator::{min,max}(_by_key)` should use overridden `min`/…
    

    Regressed in #160203. cc @scottmcm (author), @JohnTitor (reviewer)

  6. added
    T-libsRelevant to the library team, which will review and decide on the PR/issue.
    S-has-bisectionStatus: A bisection has been found for this issue
    and removed
    E-needs-bisectionCall for participation: This issue needs bisection: https://github.com/rust-lang/cargo-bisect-rustc
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Oct 11, 2026
  7. theemathas commented on Oct 11, 2026

    @theemathas
    ContributorAuthor

    Minimal reproducer:

    use std::cmp::Ordering;
    
    #[derive(PartialEq, Eq, Ord)]
    struct Thing(i32);
    
    impl PartialOrd for Thing {
        fn partial_cmp(&self, other: &Thing) -> Option<Ordering> {
            Some(self.0.cmp(&other.0).reverse())
        }
    }
    
    fn main() {
        println!("{}", [Thing(1), Thing(2)].iter().max().unwrap().0);
    }

    Outputs 2 on stable, but outputs 1 on beta.

    It seems kinda odd that it would call partial_cmp on beta. But I assume this is acceptable breakage?

  8. added
    S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issue
    and removed
    E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Example
    on Oct 11, 2026
  9. theemathas commented on Oct 11, 2026

    @theemathas
    ContributorAuthor

    Ah, it's already in the release notes: #161391

  10. asquared31415 commented on Oct 11, 2026

    @asquared31415
    Contributor

    That PR causes the iterator to start calling Ord::max, which is not overridden, so it uses the default impl which does Thing < Thing (using the < operator), which calls into partial_cmp. Previously it was reduce over Ord::cmp, which has correct behavior from the derive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-iteratorsArea: IteratorsC-bugCategory: This is a bug.I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}S-has-bisectionStatus: A bisection has been found for this issueS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-libsRelevant to the library team, which will review and decide on the PR/issue.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions