//! This module contains collection types that don't expose their internal
//! ordering. This is a useful property for deterministic computations, such
//! as required by the query system.

use std::borrow::{Borrow, BorrowMut};
use std::collections::hash_map::{Entry, OccupiedError};
use std::hash::Hash;
use std::iter::{Product, Sum};
use std::ops::Index;

use rustc_macros::{Decodable_NoContext, Encodable_NoContext};

use crate::fingerprint::Fingerprint;
use crate::fx::{FxBuildHasher, FxHashMap, FxHashSet};
use crate::stable_hash::{
    StableCompare, StableHash, StableHashCtxt, StableHasher, ToStableHashKey,
};

/// `UnordItems` is the order-less version of `Iterator`. It only contains methods
/// that don't (easily) expose an ordering of the underlying items.
///
/// Most methods take an `Fn` where the `Iterator`-version takes an `FnMut`. This
/// is to reduce the risk of accidentally leaking the internal order via the closure
/// environment. Otherwise one could easily do something like
///
/// ```rust,ignore (pseudo code)
/// let mut ordered = vec![];
/// unordered_items.all(|x| ordered.push(x));
/// ```
///
/// It's still possible to do the same thing with an `Fn` by using interior mutability,
/// but the chance of doing it accidentally is reduced.
#[derive(Clone)]
pub struct UnordItems<T, I: Iterator<Item = T>>(I);

impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
    #[inline]
    pub fn new(iter: I) -> UnordItems<T, I> {
        UnordItems(iter)
    }

    #[inline]
    pub fn map<U, F: Fn(T) -> U>(self, f: F) -> UnordItems<U, impl Iterator<Item = U>> {
        UnordItems(self.0.map(f))
    }

    #[inline]
    pub fn all<F: Fn(T) -> bool>(mut self, f: F) -> bool {
        self.0.all(f)
    }

    #[inline]
    pub fn any<F: Fn(T) -> bool>(mut self, f: F) -> bool {
        self.0.any(f)
    }

    #[inline]
    pub fn filter<F: Fn(&T) -> bool>(self, f: F) -> UnordItems<T, impl Iterator<Item = T>> {
        UnordItems(self.0.filter(f))
    }

    #[inline]
    pub fn filter_map<U, F: Fn(T) -> Option<U>>(
        self,
        f: F,
    ) -> UnordItems<U, impl Iterator<Item = U>> {
        UnordItems(self.0.filter_map(f))
    }

    #[inline]
    pub fn chain(
        self,
        other: UnordItems<T, impl Iterator<Item = T>>,
    ) -> UnordItems<T, impl Iterator<Item = T>> {
        UnordItems(self.0.chain(other.0))
    }

    #[inline]
    pub fn max(self) -> Option<T>
    where
        T: Ord,
    {
        self.0.max()
    }

    #[inline]
    pub fn min(self) -> Option<T>
    where
        T: Ord,
    {
        self.0.min()
    }

    #[inline]
    pub fn sum<S>(self) -> S
    where
        S: Sum<T>,
    {
        self.0.sum()
    }

    #[inline]
    pub fn product<S>(self) -> S
    where
        S: Product<T>,
    {
        self.0.product()
    }

    #[inline]
    pub fn count(self) -> usize {
        self.0.count()
    }

    #[inline]
    pub fn flat_map<U, F, O>(self, f: F) -> UnordItems<O, impl Iterator<Item = O>>
    where
        U: Iterator<Item = O>,
        F: Fn(T) -> UnordItems<O, U>,
    {
        UnordItems(self.0.flat_map(move |x| f(x).0))
    }

    pub fn collect<C: From<UnordItems<T, I>>>(self) -> C {
        self.into()
    }

    /// If the iterator has only one element, returns it, otherwise returns `None`.
    #[track_caller]
    pub fn get_only(mut self) -> Option<T> {
        let item = self.0.next();
        if self.0.next().is_some() {
            return None;
        }
        item
    }
}

impl<T> UnordItems<T, std::iter::Empty<T>> {
    pub fn empty() -> Self {
        UnordItems(std::iter::empty())
    }
}

impl<'a, T: Clone + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
    #[inline]
    pub fn cloned(self) -> UnordItems<T, impl Iterator<Item = T>> {
        UnordItems(self.0.cloned())
    }
}

impl<'a, T: Copy + 'a, I: Iterator<Item = &'a T>> UnordItems<&'a T, I> {
    #[inline]
    pub fn copied(self) -> UnordItems<T, impl Iterator<Item = T>> {
        UnordItems(self.0.copied())
    }
}

impl<T, I: Iterator<Item = T>> UnordItems<T, I> {
    #[inline]
    pub fn into_sorted<Hcx: StableHashCtxt>(self, hcx: &mut Hcx) -> Vec<T>
    where
        T: ToStableHashKey,
    {
        self.collect_sorted(hcx, true)
    }

    #[inline]
    pub fn into_sorted_stable_ord(self) -> Vec<T>
    where
        T: StableCompare,
    {
        self.collect_stable_ord_by_key(|x| x)
    }

    #[inline]
    pub fn into_sorted_stable_ord_by_key<K, C>(self, project_to_key: C) -> Vec<T>
    where
        K: StableCompare,
        C: for<'a> Fn(&'a T) -> &'a K,
    {
        self.collect_stable_ord_by_key(project_to_key)
    }

    #[inline]
    pub fn collect_sorted<Hcx, C>(self, hcx: &mut Hcx, cache_sort_key: bool) -> C
    where
        Hcx: StableHashCtxt,
        T: ToStableHashKey,
        C: FromIterator<T> + BorrowMut<[T]>,
    {
        let mut items: C = self.0.collect();

        let slice = items.borrow_mut();
        if slice.len() > 1 {
            if cache_sort_key {
                slice.sort_by_cached_key(|x| x.to_stable_hash_key(hcx));
            } else {
                slice.sort_by_key(|x| x.to_stable_hash_key(hcx));
            }
        }

        items
    }

    #[inline]
    pub fn collect_stable_ord_by_key<K, C, P>(self, project_to_key: P) -> C
    where
        K: StableCompare,
        P: for<'a> Fn(&'a T) -> &'a K,
        C: FromIterator<T> + BorrowMut<[T]>,
    {
        let mut items: C = self.0.collect();

        let slice = items.borrow_mut();
        if slice.len() > 1 {
            if !K::CAN_USE_UNSTABLE_SORT {
                slice.sort_by(|a, b| {
                    let a_key = project_to_key(a);
                    let b_key = project_to_key(b);
                    a_key.stable_cmp(b_key)
                });
            } else {
                slice.sort_unstable_by(|a, b| {
                    let a_key = project_to_key(a);
                    let b_key = project_to_key(b);
                    a_key.stable_cmp(b_key)
                });
            }
        }

        items
    }
}

/// A marker trait specifying that `Self` can consume `UnordItems<_>` without
/// exposing any internal ordering.
///
/// Note: right now this is just a marker trait. It could be extended to contain
/// some useful, common methods though, like `len`, `clear`, or the various
/// kinds of `to_sorted`.
trait UnordCollection {}

/// This is a set collection type that tries very hard to not expose
/// any internal iteration. This is a useful property when trying to
/// uphold the determinism invariants imposed by the query system.
///
/// This collection type is a good choice for set-like collections the
/// keys of which don't have a semantic ordering.
///
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
/// for more information.
#[derive(Debug, Eq, PartialEq, Clone, Encodable_NoContext, Decodable_NoContext)]
pub struct UnordSet<V: Eq + Hash> {
    inner: FxHashSet<V>,
}

impl<V: Eq + Hash> UnordCollection for UnordSet<V> {}

const impl<V: Eq + Hash> Default for UnordSet<V> {
    #[inline]
    fn default() -> Self {
        Self { inner: FxHashSet::with_hasher(FxBuildHasher) }
    }
}

impl<V: Eq + Hash> UnordSet<V> {
    #[inline]
    pub fn new() -> Self {
        Self { inner: Default::default() }
    }

    #[inline]
    pub fn with_capacity(capacity: usize) -> Self {
        Self { inner: FxHashSet::with_capacity_and_hasher(capacity, Default::default()) }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }

    /// If the set has only one element, returns it, otherwise returns `None`.
    #[inline]
    pub fn get_only(&self) -> Option<&V> {
        if self.inner.len() == 1 { self.inner.iter().next() } else { None }
    }

    #[inline]
    pub fn insert(&mut self, v: V) -> bool {
        self.inner.insert(v)
    }

    #[inline]
    pub fn contains<Q: ?Sized>(&self, v: &Q) -> bool
    where
        V: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.inner.contains(v)
    }

    #[inline]
    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> bool
    where
        V: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.inner.remove(k)
    }

    #[inline]
    pub fn items(&self) -> UnordItems<&V, impl Iterator<Item = &V>> {
        UnordItems(self.inner.iter())
    }

    #[inline]
    pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
        UnordItems(self.inner.into_iter())
    }

    /// Returns the items of this set in stable sort order (as defined by `ToStableHashKey`).
    ///
    /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
    /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
    /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
    /// for `V` is expensive (e.g. a `DefId -> DefPathHash` lookup).
    #[inline]
    pub fn to_sorted<Hcx>(&self, hcx: &mut Hcx, cache_sort_key: bool) -> Vec<&V>
    where
        Hcx: StableHashCtxt,
        V: ToStableHashKey,
    {
        to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&x| x)
    }

    /// Returns the items of this set in stable sort order (as defined by
    /// `StableCompare`). This method is much more efficient than
    /// `into_sorted` because it does not need to transform keys to their
    /// `ToStableHashKey` equivalent.
    #[inline]
    pub fn to_sorted_stable_ord(&self) -> Vec<&V>
    where
        V: StableCompare,
    {
        let mut items: Vec<&V> = self.inner.iter().collect();
        items.sort_unstable_by(|a, b| a.stable_cmp(*b));
        items
    }

    /// Returns the items of this set in stable sort order (as defined by
    /// `StableCompare`). This method is much more efficient than
    /// `into_sorted` because it does not need to transform keys to their
    /// `ToStableHashKey` equivalent.
    #[inline]
    pub fn into_sorted_stable_ord(self) -> Vec<V>
    where
        V: StableCompare,
    {
        let mut items: Vec<V> = self.inner.into_iter().collect();
        items.sort_unstable_by(V::stable_cmp);
        items
    }

    /// Returns the items of this set in stable sort order (as defined by `ToStableHashKey`).
    ///
    /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
    /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
    /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
    /// for `V` is expensive (e.g. a `DefId -> DefPathHash` lookup).
    #[inline]
    pub fn into_sorted<Hcx>(self, hcx: &mut Hcx, cache_sort_key: bool) -> Vec<V>
    where
        Hcx: StableHashCtxt,
        V: ToStableHashKey,
    {
        to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |x| x)
    }

    #[inline]
    pub fn clear(&mut self) {
        self.inner.clear();
    }
}

pub trait ExtendUnord<T> {
    /// Extend this unord collection with the given `UnordItems`.
    /// This method is called `extend_unord` instead of just `extend` so it
    /// does not conflict with `Extend::extend`. Otherwise there would be many
    /// places where the two methods would have to be explicitly disambiguated
    /// via UFCS.
    fn extend_unord<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>);
}

// Note: it is important that `C` implements `UnordCollection` in addition to
// `Extend`, otherwise this impl would leak the internal iteration order of
// `items`, e.g. when calling `some_vec.extend_unord(some_unord_items)`.
impl<C: Extend<T> + UnordCollection, T> ExtendUnord<T> for C {
    #[inline]
    fn extend_unord<I: Iterator<Item = T>>(&mut self, items: UnordItems<T, I>) {
        self.extend(items.0)
    }
}

impl<V: Hash + Eq> Extend<V> for UnordSet<V> {
    #[inline]
    fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
        self.inner.extend(iter)
    }
}

impl<V: Hash + Eq> FromIterator<V> for UnordSet<V> {
    #[inline]
    fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
        UnordSet { inner: FxHashSet::from_iter(iter) }
    }
}

impl<V: Hash + Eq> From<FxHashSet<V>> for UnordSet<V> {
    fn from(value: FxHashSet<V>) -> Self {
        UnordSet { inner: value }
    }
}

impl<V: Hash + Eq, I: Iterator<Item = V>> From<UnordItems<V, I>> for UnordSet<V> {
    fn from(value: UnordItems<V, I>) -> Self {
        UnordSet { inner: FxHashSet::from_iter(value.0) }
    }
}

impl<V: Hash + Eq + StableHash> StableHash for UnordSet<V> {
    #[inline]
    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
        hash_iter_order_independent(self.inner.iter(), hcx, hasher);
    }
}

/// This is a map collection type that tries very hard to not expose
/// any internal iteration. This is a useful property when trying to
/// uphold the determinism invariants imposed by the query system.
///
/// This collection type is a good choice for map-like collections the
/// keys of which don't have a semantic ordering.
///
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
/// for more information.
#[derive(Debug, Eq, PartialEq, Clone, Encodable_NoContext, Decodable_NoContext)]
pub struct UnordMap<K: Eq + Hash, V> {
    inner: FxHashMap<K, V>,
}

impl<K: Eq + Hash, V> UnordCollection for UnordMap<K, V> {}

const impl<K: Eq + Hash, V> Default for UnordMap<K, V> {
    #[inline]
    fn default() -> Self {
        Self { inner: FxHashMap::with_hasher(FxBuildHasher) }
    }
}

impl<K: Hash + Eq, V> Extend<(K, V)> for UnordMap<K, V> {
    #[inline]
    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
        self.inner.extend(iter)
    }
}

impl<K: Hash + Eq, V> FromIterator<(K, V)> for UnordMap<K, V> {
    #[inline]
    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
        UnordMap { inner: FxHashMap::from_iter(iter) }
    }
}

impl<K: Hash + Eq, V, I: Iterator<Item = (K, V)>> From<UnordItems<(K, V), I>> for UnordMap<K, V> {
    #[inline]
    fn from(items: UnordItems<(K, V), I>) -> Self {
        UnordMap { inner: FxHashMap::from_iter(items.0) }
    }
}

impl<K: Eq + Hash, V> UnordMap<K, V> {
    #[inline]
    pub fn with_capacity(capacity: usize) -> Self {
        Self { inner: FxHashMap::with_capacity_and_hasher(capacity, Default::default()) }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    #[inline]
    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
        self.inner.insert(k, v)
    }

    #[inline]
    pub fn try_insert(&mut self, k: K, v: V) -> Result<&mut V, OccupiedError<'_, K, V>> {
        self.inner.try_insert(k, v)
    }

    #[inline]
    pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
    where
        K: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.inner.contains_key(k)
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }

    #[inline]
    pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
        self.inner.entry(key)
    }

    #[inline]
    pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.inner.get(k)
    }

    #[inline]
    pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.inner.get_mut(k)
    }

    #[inline]
    pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
    where
        K: Borrow<Q>,
        Q: Hash + Eq,
    {
        self.inner.remove(k)
    }

    #[inline]
    pub fn items(&self) -> UnordItems<(&K, &V), impl Iterator<Item = (&K, &V)>> {
        UnordItems(self.inner.iter())
    }

    #[inline]
    pub fn into_items(self) -> UnordItems<(K, V), impl Iterator<Item = (K, V)>> {
        UnordItems(self.inner.into_iter())
    }

    #[inline]
    pub fn keys(&self) -> UnordItems<&K, impl Iterator<Item = &K>> {
        UnordItems(self.inner.keys())
    }

    /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
    ///
    /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
    /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
    /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
    /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup).
    #[inline]
    pub fn to_sorted<Hcx>(&self, hcx: &mut Hcx, cache_sort_key: bool) -> Vec<(&K, &V)>
    where
        Hcx: StableHashCtxt,
        K: ToStableHashKey,
    {
        to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&(k, _)| k)
    }

    /// Returns the entries of this map in stable sort order (as defined by `StableCompare`).
    /// This method can be much more efficient than `into_sorted` because it does not need
    /// to transform keys to their `ToStableHashKey` equivalent.
    #[inline]
    pub fn to_sorted_stable_ord(&self) -> Vec<(&K, &V)>
    where
        K: StableCompare,
    {
        let mut items: Vec<_> = self.inner.iter().collect();
        items.sort_unstable_by(|(a, _), (b, _)| a.stable_cmp(*b));
        items
    }

    /// Returns the entries of this map in stable sort order (as defined by `ToStableHashKey`).
    ///
    /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
    /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
    /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
    /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup).
    #[inline]
    pub fn into_sorted<Hcx>(self, hcx: &mut Hcx, cache_sort_key: bool) -> Vec<(K, V)>
    where
        Hcx: StableHashCtxt,
        K: ToStableHashKey,
    {
        to_sorted_vec(hcx, self.inner.into_iter(), cache_sort_key, |(k, _)| k)
    }

    /// Returns the entries of this map in stable sort order (as defined by `StableCompare`).
    /// This method can be much more efficient than `into_sorted` because it does not need
    /// to transform keys to their `ToStableHashKey` equivalent.
    #[inline]
    pub fn into_sorted_stable_ord(self) -> Vec<(K, V)>
    where
        K: StableCompare,
    {
        let mut items: Vec<(K, V)> = self.inner.into_iter().collect();
        items.sort_unstable_by(|a, b| a.0.stable_cmp(&b.0));
        items
    }

    /// Returns the values of this map in stable sort order (as defined by K's
    /// `ToStableHashKey` implementation).
    ///
    /// The `cache_sort_key` parameter controls if [slice::sort_by_cached_key] or
    /// [slice::sort_unstable_by_key] will be used for sorting the vec. Use
    /// `cache_sort_key` when the [ToStableHashKey::to_stable_hash_key] implementation
    /// for `K` is expensive (e.g. a `DefId -> DefPathHash` lookup).
    #[inline]
    pub fn values_sorted<Hcx>(
        &self,
        hcx: &mut Hcx,
        cache_sort_key: bool,
    ) -> impl Iterator<Item = &V>
    where
        Hcx: StableHashCtxt,
        K: ToStableHashKey,
    {
        to_sorted_vec(hcx, self.inner.iter(), cache_sort_key, |&(k, _)| k)
            .into_iter()
            .map(|(_, v)| v)
    }

    #[inline]
    pub fn clear(&mut self) {
        self.inner.clear()
    }
}

impl<K, Q: ?Sized, V> Index<&Q> for UnordMap<K, V>
where
    K: Eq + Hash + Borrow<Q>,
    Q: Eq + Hash,
{
    type Output = V;

    #[inline]
    fn index(&self, key: &Q) -> &V {
        &self.inner[key]
    }
}

impl<K: Hash + Eq + StableHash, V: StableHash> StableHash for UnordMap<K, V> {
    #[inline]
    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
        hash_iter_order_independent(self.inner.iter(), hcx, hasher);
    }
}

/// This is a collection type that tries very hard to not expose
/// any internal iteration. This is a useful property when trying to
/// uphold the determinism invariants imposed by the query system.
///
/// This collection type is a good choice for collections the
/// keys of which don't have a semantic ordering and don't implement
/// `Hash` or `Eq`.
///
/// See [MCP 533](https://github.com/rust-lang/compiler-team/issues/533)
/// for more information.
#[derive(Default, Debug, Eq, PartialEq, Clone, Encodable_NoContext, Decodable_NoContext)]
pub struct UnordBag<V> {
    inner: Vec<V>,
}

impl<V> UnordBag<V> {
    #[inline]
    pub fn new() -> Self {
        Self { inner: Default::default() }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    #[inline]
    pub fn push(&mut self, v: V) {
        self.inner.push(v);
    }

    #[inline]
    pub fn items(&self) -> UnordItems<&V, impl Iterator<Item = &V>> {
        UnordItems(self.inner.iter())
    }

    #[inline]
    pub fn into_items(self) -> UnordItems<V, impl Iterator<Item = V>> {
        UnordItems(self.inner.into_iter())
    }
}

impl<T> UnordCollection for UnordBag<T> {}

impl<T> Extend<T> for UnordBag<T> {
    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
        self.inner.extend(iter)
    }
}

impl<T, I: Iterator<Item = T>> From<UnordItems<T, I>> for UnordBag<T> {
    fn from(value: UnordItems<T, I>) -> Self {
        UnordBag { inner: Vec::from_iter(value.0) }
    }
}

impl<V: Hash + Eq + StableHash> StableHash for UnordBag<V> {
    #[inline]
    fn stable_hash<Hcx: StableHashCtxt>(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
        hash_iter_order_independent(self.inner.iter(), hcx, hasher);
    }
}

#[inline]
fn to_sorted_vec<Hcx, T, K, I>(
    hcx: &mut Hcx,
    iter: I,
    cache_sort_key: bool,
    extract_key: fn(&T) -> &K,
) -> Vec<T>
where
    Hcx: StableHashCtxt,
    I: Iterator<Item = T>,
    K: ToStableHashKey,
{
    let mut items: Vec<T> = iter.collect();
    if cache_sort_key {
        items.sort_by_cached_key(|x| extract_key(x).to_stable_hash_key(hcx));
    } else {
        items.sort_unstable_by_key(|x| extract_key(x).to_stable_hash_key(hcx));
    }

    items
}

fn hash_iter_order_independent<
    Hcx: StableHashCtxt,
    T: StableHash,
    I: Iterator<Item = T> + ExactSizeIterator,
>(
    mut it: I,
    hcx: &mut Hcx,
    hasher: &mut StableHasher,
) {
    let len = it.len();
    len.stable_hash(hcx, hasher);

    match len {
        0 => {
            // We're done
        }
        1 => {
            // No need to instantiate a hasher
            it.next().unwrap().stable_hash(hcx, hasher);
        }
        _ => {
            let mut accumulator = Fingerprint::ZERO;
            for item in it {
                let mut item_hasher = StableHasher::new();
                item.stable_hash(hcx, &mut item_hasher);
                let item_fingerprint: Fingerprint = item_hasher.finish();
                accumulator = accumulator.combine_commutative(item_fingerprint);
            }
            accumulator.stable_hash(hcx, hasher);
        }
    }
}

// Do not implement IntoIterator for the collections in this module.
// They only exist to hide iteration order in the first place.
impl<T> !IntoIterator for UnordBag<T> {}
impl<V> !IntoIterator for UnordSet<V> {}
impl<K, V> !IntoIterator for UnordMap<K, V> {}
impl<T, I> !IntoIterator for UnordItems<T, I> {}
