Collection Adapters and Specialized Types

Reverse<T>

std::cmp::Reverse<T> is a zero-cost tuple struct wrapper (#[repr(transparent)] pub struct Reverse<T>(pub T);) that inverts the comparison order of its inner value T.

Definition and Trait Implementations

#[derive(PartialEq, Eq, Debug, Copy, Clone, Default, Hash)]
#[repr(transparent)]
pub struct Reverse<T>(pub T);

impl<T: PartialOrd> PartialOrd for Reverse<T> {
    fn partial_cmp(&self, other: &Reverse<T>) -> Option<Ordering> {
        other.0.partial_cmp(&self.0) // Swaps `self` and `other`!
    }
}

impl<T: Ord> Ord for Reverse<T> {
    fn cmp(&self, other: &Reverse<T>) -> Ordering {
        other.0.cmp(&self.0) // Swaps `self` and `other`!
    }
}

Because Reverse<T> is annotated with #[repr(transparent)], it has the exact same memory layout, size, and ABI as T itself (size_of::<Reverse<T>>() == size_of::<T>()), and its inner value is publicly accessible via .0 or pattern destructuring Reverse(val).

Comparison on T Equivalent Comparison on Reverse<T>
a < b Reverse(a) > Reverse(b)
a > b Reverse(a) < Reverse(b)
a == b Reverse(a) == Reverse(b)

Multi-Column Sorting (Mixed Ascending and Descending Keys)

Beyond turning BinaryHeap<Reverse<T>> into a min-heap or BTreeMap<Reverse<K>, V> into a descending map, Reverse<T> is the standard way to express mixed-direction sorting inside .sort_by_key() or .sort_unstable_by_key() by wrapping only the descending fields of a tuple key:

use std::cmp::Reverse;

#[derive(Debug)]
struct Player {
    name: &'static str,
    score: u32,
    penalties: u32,
}

fn main() {
    let mut leaderboard = vec![
        Player { name: "carol", score: 150, penalties: 2 },
        Player { name: "alice", score: 200, penalties: 5 },
        Player { name: "bob",   score: 200, penalties: 1 },
        Player { name: "dave",  score: 200, penalties: 1 },
    ];

    // Sort by:
    //   1. `score` DESCENDING (`Reverse(p.score)`)
    //   2. `penalties` ASCENDING (`p.penalties`)
    //   3. `name` ASCENDING (`p.name`)
    leaderboard.sort_unstable_by_key(|p| (Reverse(p.score), p.penalties, p.name));

    for (rank, p) in leaderboard.iter().enumerate() {
        println!(
            "#{}: {:<6} (score={}, penalties={})",
            rank + 1,
            p.name,
            p.score,
            p.penalties
        );
    }
}
#1: bob    (score=200, penalties=1)
#2: dave   (score=200, penalties=1)
#3: alice  (score=200, penalties=5)
#4: carol  (score=150, penalties=2)

Descending Keys in BTreeMap and BTreeSet

Wrapping the key of a BTreeMap<Reverse<K>, V> or BTreeSet<Reverse<T>> stores and iterates elements from largest to smallest while preserving .range() and .first_key_value() semantics in descending order:

use std::cmp::Reverse;
use std::collections::BTreeSet;

fn main() {
    let mut high_scores = BTreeSet::from([Reverse(120), Reverse(450), Reverse(300)]);
    high_scores.insert(Reverse(500));

    // `.first()` on `BTreeSet<Reverse<i32>>` returns the highest score:
    println!("Highest score: {:?}", high_scores.first().map(|r| r.0));

    let ordered: Vec<i32> = high_scores.into_iter().map(|Reverse(s)| s).collect();
    println!("All scores descending: {ordered:?}");
}
Highest score: Some(500)
All scores descending: [500, 450, 300, 120]