//! # Replacement range types
//!
//! The types within this module are meant to replace the legacy `Range`,
//! `RangeInclusive`, `RangeToInclusive` and `RangeFrom` types in a future edition.
//!
//! ```
//! use core::range::{Range, RangeFrom, RangeInclusive, RangeToInclusive};
//!
//! let arr = [0, 1, 2, 3, 4];
//! assert_eq!(arr[                        ..   ], [0, 1, 2, 3, 4]);
//! assert_eq!(arr[                        .. 3 ], [0, 1, 2      ]);
//! assert_eq!(arr[RangeToInclusive::from( ..=3)], [0, 1, 2, 3   ]);
//! assert_eq!(arr[       RangeFrom::from(1..  )], [   1, 2, 3, 4]);
//! assert_eq!(arr[           Range::from(1..3 )], [   1, 2      ]);
//! assert_eq!(arr[  RangeInclusive::from(1..=3)], [   1, 2, 3   ]);
//! ```

use crate::fmt;
use crate::hash::Hash;

mod iter;

#[stable(feature = "new_range_api_legacy", since = "1.98.0")]
pub mod legacy;

use core::ops::Bound::{self, Excluded, Included, Unbounded};

#[doc(inline)]
#[stable(feature = "new_range_from_api", since = "1.96.0")]
pub use iter::RangeFromIter;
#[doc(inline)]
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
pub use iter::RangeInclusiveIter;
#[doc(inline)]
#[stable(feature = "new_range_api", since = "1.96.0")]
pub use iter::RangeIter;

use crate::iter::Step;
// FIXME(one_sided_range): These types should move into this module.
// FIXME(range_into_bounds): Ditto. Also consider re-exporting `RangeBounds` and related.
use crate::ops::{IntoBounds, OneSidedRange, OneSidedRangeBound, RangeBounds};
#[doc(inline)]
#[stable(feature = "new_range_api_exports", since = "1.98.0")]
pub use crate::ops::{RangeFull, RangeTo};

/// A (half-open) range bounded inclusively below and exclusively above.
///
/// The `Range` contains all values with `start <= x < end`.
/// It is empty if `start >= end`.
///
/// # Examples
///
/// ```
/// use core::range::Range;
///
/// assert_eq!(Range::from(3..5), Range { start: 3, end: 5 });
/// assert_eq!(3 + 4 + 5, Range::from(3..6).into_iter().sum());
/// ```
///
/// # Edition notes
///
/// It is planned that the syntax `start..end` will construct this
/// type in a future edition, but it does not do so today.
#[lang = "RangeCopy"]
#[derive(Copy, Hash)]
#[derive_const(Clone, Default, PartialEq, Eq)]
#[stable(feature = "new_range_api", since = "1.96.0")]
pub struct Range<Idx> {
    /// The lower bound of the range (inclusive).
    #[stable(feature = "new_range_api", since = "1.96.0")]
    pub start: Idx,
    /// The upper bound of the range (exclusive).
    #[stable(feature = "new_range_api", since = "1.96.0")]
    pub end: Idx,
}

#[stable(feature = "new_range_api", since = "1.96.0")]
impl<Idx: fmt::Debug> fmt::Debug for Range<Idx> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.start.fmt(fmt)?;
        write!(fmt, "..")?;
        self.end.fmt(fmt)?;
        Ok(())
    }
}

impl<Idx: Step> Range<Idx> {
    /// Creates an iterator over the elements within this range.
    ///
    /// Shorthand for `.clone().into_iter()`
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::Range;
    ///
    /// let mut i = Range::from(3..9).iter().map(|n| n*n);
    /// assert_eq!(i.next(), Some(9));
    /// assert_eq!(i.next(), Some(16));
    /// assert_eq!(i.next(), Some(25));
    /// ```
    #[stable(feature = "new_range_api", since = "1.96.0")]
    #[inline]
    pub fn iter(&self) -> RangeIter<Idx> {
        self.clone().into_iter()
    }
}

impl<Idx: PartialOrd<Idx>> Range<Idx> {
    /// Returns `true` if `item` is contained in the range.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::Range;
    ///
    /// assert!(!Range::from(3..5).contains(&2));
    /// assert!( Range::from(3..5).contains(&3));
    /// assert!( Range::from(3..5).contains(&4));
    /// assert!(!Range::from(3..5).contains(&5));
    ///
    /// assert!(!Range::from(3..3).contains(&3));
    /// assert!(!Range::from(3..2).contains(&3));
    ///
    /// assert!( Range::from(0.0..1.0).contains(&0.5));
    /// assert!(!Range::from(0.0..1.0).contains(&f32::NAN));
    /// assert!(!Range::from(0.0..f32::NAN).contains(&0.5));
    /// assert!(!Range::from(f32::NAN..1.0).contains(&0.5));
    /// ```
    #[inline]
    #[stable(feature = "new_range_api", since = "1.96.0")]
    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    pub const fn contains<U>(&self, item: &U) -> bool
    where
        Idx: [const] PartialOrd<U>,
        U: ?Sized + [const] PartialOrd<Idx>,
    {
        <Self as RangeBounds<Idx>>::contains(self, item)
    }

    /// Returns `true` if the range contains no items.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::Range;
    ///
    /// assert!(!Range::from(3..5).is_empty());
    /// assert!( Range::from(3..3).is_empty());
    /// assert!( Range::from(3..2).is_empty());
    /// ```
    ///
    /// The range is empty if either side is incomparable:
    ///
    /// ```
    /// use core::range::Range;
    ///
    /// assert!(!Range::from(3.0..5.0).is_empty());
    /// assert!( Range::from(3.0..f32::NAN).is_empty());
    /// assert!( Range::from(f32::NAN..5.0).is_empty());
    /// ```
    #[inline]
    #[stable(feature = "new_range_api", since = "1.96.0")]
    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    pub const fn is_empty(&self) -> bool
    where
        Idx: [const] PartialOrd,
    {
        !(self.start < self.end)
    }
}

#[stable(feature = "new_range_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> RangeBounds<T> for Range<T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Excluded(&self.end)
    }
}

// This impl intentionally does not have `T: ?Sized`;
// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
//
/// If you need to use this implementation where `T` is unsized,
/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
/// i.e. replace `start..end` with `(Bound::Included(start), Bound::Excluded(end))`.
#[stable(feature = "new_range_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> RangeBounds<T> for Range<&T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Excluded(self.end)
    }
}

#[unstable(feature = "range_into_bounds", issue = "136903")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> IntoBounds<T> for Range<T> {
    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
        (Included(self.start), Excluded(self.end))
    }
}

#[stable(feature = "new_range_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl<T> From<Range<T>> for legacy::Range<T> {
    #[inline]
    fn from(value: Range<T>) -> Self {
        Self { start: value.start, end: value.end }
    }
}
#[stable(feature = "new_range_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl<T> From<legacy::Range<T>> for Range<T> {
    #[inline]
    fn from(value: legacy::Range<T>) -> Self {
        Self { start: value.start, end: value.end }
    }
}

/// A range bounded inclusively below and above.
///
/// The `RangeInclusive` contains all values with `x >= start`
/// and `x <= last`. It is empty unless `start <= last`.
///
/// # Examples
///
/// ```
/// use core::range::RangeInclusive;
///
/// assert_eq!(RangeInclusive::from(3..=5), RangeInclusive { start: 3, last: 5 });
/// assert_eq!(3 + 4 + 5, RangeInclusive::from(3..=5).into_iter().sum());
/// ```
///
/// # Edition notes
///
/// It is planned that the syntax  `start..=last` will construct this
/// type in a future edition, but it does not do so today.
#[lang = "RangeInclusiveCopy"]
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
pub struct RangeInclusive<Idx> {
    /// The lower bound of the range (inclusive).
    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
    pub start: Idx,
    /// The upper bound of the range (inclusive).
    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
    pub last: Idx,
}

#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
impl<Idx: fmt::Debug> fmt::Debug for RangeInclusive<Idx> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.start.fmt(fmt)?;
        write!(fmt, "..=")?;
        self.last.fmt(fmt)?;
        Ok(())
    }
}

impl<Idx: PartialOrd<Idx>> RangeInclusive<Idx> {
    /// Returns `true` if `item` is contained in the range.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::RangeInclusive;
    ///
    /// assert!(!RangeInclusive::from(3..=5).contains(&2));
    /// assert!( RangeInclusive::from(3..=5).contains(&3));
    /// assert!( RangeInclusive::from(3..=5).contains(&4));
    /// assert!( RangeInclusive::from(3..=5).contains(&5));
    /// assert!(!RangeInclusive::from(3..=5).contains(&6));
    ///
    /// assert!( RangeInclusive::from(3..=3).contains(&3));
    /// assert!(!RangeInclusive::from(3..=2).contains(&3));
    ///
    /// assert!( RangeInclusive::from(0.0..=1.0).contains(&1.0));
    /// assert!(!RangeInclusive::from(0.0..=1.0).contains(&f32::NAN));
    /// assert!(!RangeInclusive::from(0.0..=f32::NAN).contains(&0.0));
    /// assert!(!RangeInclusive::from(f32::NAN..=1.0).contains(&1.0));
    /// ```
    #[inline]
    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    pub const fn contains<U>(&self, item: &U) -> bool
    where
        Idx: [const] PartialOrd<U>,
        U: ?Sized + [const] PartialOrd<Idx>,
    {
        <Self as RangeBounds<Idx>>::contains(self, item)
    }

    /// Returns `true` if the range contains no items.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::RangeInclusive;
    ///
    /// assert!(!RangeInclusive::from(3..=5).is_empty());
    /// assert!(!RangeInclusive::from(3..=3).is_empty());
    /// assert!( RangeInclusive::from(3..=2).is_empty());
    /// ```
    ///
    /// The range is empty if either side is incomparable:
    ///
    /// ```
    /// use core::range::RangeInclusive;
    ///
    /// assert!(!RangeInclusive::from(3.0..=5.0).is_empty());
    /// assert!( RangeInclusive::from(3.0..=f32::NAN).is_empty());
    /// assert!( RangeInclusive::from(f32::NAN..=5.0).is_empty());
    /// ```
    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
    #[inline]
    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    pub const fn is_empty(&self) -> bool
    where
        Idx: [const] PartialOrd,
    {
        !(self.start <= self.last)
    }
}

impl<Idx: Step> RangeInclusive<Idx> {
    /// Creates an iterator over the elements within this range.
    ///
    /// Shorthand for `.clone().into_iter()`
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::RangeInclusive;
    ///
    /// let mut i = RangeInclusive::from(3..=8).iter().map(|n| n*n);
    /// assert_eq!(i.next(), Some(9));
    /// assert_eq!(i.next(), Some(16));
    /// assert_eq!(i.next(), Some(25));
    /// ```
    #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
    #[inline]
    pub fn iter(&self) -> RangeInclusiveIter<Idx> {
        self.clone().into_iter()
    }
}

#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> RangeBounds<T> for RangeInclusive<T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Included(&self.last)
    }
}

// This impl intentionally does not have `T: ?Sized`;
// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
//
/// If you need to use this implementation where `T` is unsized,
/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
/// i.e. replace `start..=end` with `(Bound::Included(start), Bound::Included(end))`.
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> RangeBounds<T> for RangeInclusive<&T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Included(self.last)
    }
}

// #[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
#[unstable(feature = "range_into_bounds", issue = "136903")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> IntoBounds<T> for RangeInclusive<T> {
    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
        (Included(self.start), Included(self.last))
    }
}

#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl<T> From<RangeInclusive<T>> for legacy::RangeInclusive<T> {
    #[inline]
    fn from(value: RangeInclusive<T>) -> Self {
        Self::new(value.start, value.last)
    }
}
#[stable(feature = "new_range_inclusive_api", since = "1.95.0")]
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
const impl<T> From<legacy::RangeInclusive<T>> for RangeInclusive<T> {
    /// Converts from a legacy range to a non-legacy range, potentially panicking.
    ///
    /// # Panics
    ///
    /// If the legacy range iterator has been exhausted,
    /// this function will either panic or return an empty range.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::legacy;
    /// use core::range::RangeInclusive;
    ///
    /// let single: legacy::RangeInclusive<i32> = 0..=1;
    /// let single = RangeInclusive::from(single);
    /// assert_eq!((single.start, single.last), (0, 1));
    ///
    /// let empty: legacy::RangeInclusive<i32> = 0..=0;
    /// let empty = RangeInclusive::from(empty);
    /// assert_eq!((empty.start, empty.last), (0, 0));
    /// ```
    ///
    /// ```
    /// # // This test requires unwinding to work.
    /// # // Disable it when unwinding isn't available.
    /// # #[cfg(panic = "unwind")]
    /// # fn main() {
    /// use core::range::legacy;
    /// use core::range::RangeInclusive;
    /// use std::panic::catch_unwind;
    ///
    /// let mut exhausted: legacy::RangeInclusive<i32> = 0..=0;
    /// exhausted.next();
    /// let result = catch_unwind(|| RangeInclusive::from(exhausted));
    /// // The `from` call either panicked or returned an empty range.
    /// assert!(result.is_err() || result.is_ok_and(|range| range.is_empty()));
    /// # }
    /// # #[cfg(not(panic = "unwind"))]
    /// # fn main() {}
    /// ```
    #[inline]
    fn from(value: legacy::RangeInclusive<T>) -> Self {
        assert!(
            !value.exhausted,
            "attempted to convert from an exhausted `legacy::RangeInclusive`"
        );

        let (start, last) = value.into_inner();
        RangeInclusive { start, last }
    }
}

/// A range only bounded inclusively below.
///
/// The `RangeFrom` contains all values with `x >= start`.
///
/// *Note*: Overflow in the [`IntoIterator`] implementation (when the contained
/// data type reaches its numerical limit) is allowed to panic, wrap, or
/// saturate. This behavior is defined by the implementation of the [`Step`]
/// trait. For primitive integers, this follows the normal rules, and respects
/// the overflow checks profile (panic in debug, wrap in release). Unlike
/// its legacy counterpart, the iterator will only panic after yielding the
/// maximum value when overflow checks are enabled.
///
/// [`Step`]: crate::iter::Step
///
/// # Examples
///
/// ```
/// use core::range::RangeFrom;
///
/// assert_eq!(RangeFrom::from(2..), core::range::RangeFrom { start: 2 });
/// assert_eq!(2 + 3 + 4, RangeFrom::from(2..).into_iter().take(3).sum());
/// ```
///
/// # Edition notes
///
/// It is planned that the syntax  `start..` will construct this
/// type in a future edition, but it does not do so today.
#[lang = "RangeFromCopy"]
#[derive(Copy, Hash)]
#[derive_const(Clone, PartialEq, Eq)]
#[stable(feature = "new_range_from_api", since = "1.96.0")]
pub struct RangeFrom<Idx> {
    /// The lower bound of the range (inclusive).
    #[stable(feature = "new_range_from_api", since = "1.96.0")]
    pub start: Idx,
}

#[stable(feature = "new_range_from_api", since = "1.96.0")]
impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.start.fmt(fmt)?;
        write!(fmt, "..")?;
        Ok(())
    }
}

impl<Idx: Step> RangeFrom<Idx> {
    /// Creates an iterator over the elements within this range.
    ///
    /// Shorthand for `.clone().into_iter()`
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::RangeFrom;
    ///
    /// let mut i = RangeFrom::from(3..).iter().map(|n| n*n);
    /// assert_eq!(i.next(), Some(9));
    /// assert_eq!(i.next(), Some(16));
    /// assert_eq!(i.next(), Some(25));
    /// ```
    #[stable(feature = "new_range_from_api", since = "1.96.0")]
    #[inline]
    pub fn iter(&self) -> RangeFromIter<Idx> {
        self.clone().into_iter()
    }
}

impl<Idx: PartialOrd<Idx>> RangeFrom<Idx> {
    /// Returns `true` if `item` is contained in the range.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::range::RangeFrom;
    ///
    /// assert!(!RangeFrom::from(3..).contains(&2));
    /// assert!( RangeFrom::from(3..).contains(&3));
    /// assert!( RangeFrom::from(3..).contains(&1_000_000_000));
    ///
    /// assert!( RangeFrom::from(0.0..).contains(&0.5));
    /// assert!(!RangeFrom::from(0.0..).contains(&f32::NAN));
    /// assert!(!RangeFrom::from(f32::NAN..).contains(&0.5));
    /// ```
    #[inline]
    #[stable(feature = "new_range_from_api", since = "1.96.0")]
    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    pub const fn contains<U>(&self, item: &U) -> bool
    where
        Idx: [const] PartialOrd<U>,
        U: ?Sized + [const] PartialOrd<Idx>,
    {
        <Self as RangeBounds<Idx>>::contains(self, item)
    }
}

#[stable(feature = "new_range_from_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> RangeBounds<T> for RangeFrom<T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(&self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Unbounded
    }
}

// This impl intentionally does not have `T: ?Sized`;
// see https://github.com/rust-lang/rust/pull/61584 for discussion of why.
//
/// If you need to use this implementation where `T` is unsized,
/// consider using the `RangeBounds` impl for a 2-tuple of [`Bound<&T>`][Bound],
/// i.e. replace `start..` with `(Bound::Included(start), Bound::Unbounded)`.
#[stable(feature = "new_range_from_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> RangeBounds<T> for RangeFrom<&T> {
    fn start_bound(&self) -> Bound<&T> {
        Included(self.start)
    }
    fn end_bound(&self) -> Bound<&T> {
        Unbounded
    }
}

#[unstable(feature = "range_into_bounds", issue = "136903")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> IntoBounds<T> for RangeFrom<T> {
    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
        (Included(self.start), Unbounded)
    }
}

#[unstable(feature = "one_sided_range", issue = "69780")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> OneSidedRange<T> for RangeFrom<T>
where
    Self: RangeBounds<T>,
{
    fn bound(self) -> (OneSidedRangeBound, T) {
        (OneSidedRangeBound::StartInclusive, self.start)
    }
}

#[stable(feature = "new_range_from_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
const impl<T> From<RangeFrom<T>> for legacy::RangeFrom<T> {
    #[inline]
    fn from(value: RangeFrom<T>) -> Self {
        Self { start: value.start }
    }
}
#[stable(feature = "new_range_from_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_index", issue = "143775")]
const impl<T> From<legacy::RangeFrom<T>> for RangeFrom<T> {
    #[inline]
    fn from(value: legacy::RangeFrom<T>) -> Self {
        Self { start: value.start }
    }
}

/// A range only bounded inclusively above.
///
/// The `RangeToInclusive` contains all values with `x <= last`.
/// It cannot serve as an [`Iterator`] because it doesn't have a starting point.
///
/// # Examples
///
/// ```standalone_crate
/// #![feature(new_range)]
/// assert_eq!((..=5), std::range::RangeToInclusive { last: 5 });
/// ```
///
/// It does not have an [`IntoIterator`] implementation, so you can't use it in a
/// `for` loop directly. This won't compile:
///
/// ```compile_fail,E0277
/// // error[E0277]: the trait bound `std::range::RangeToInclusive<{integer}>:
/// // std::iter::Iterator` is not satisfied
/// for i in ..=5 {
///     // ...
/// }
/// ```
///
/// When used as a [slicing index], `RangeToInclusive` produces a slice of all
/// array elements up to and including the index indicated by `last`.
///
/// ```
/// let arr = [0, 1, 2, 3, 4];
/// assert_eq!(arr[ ..  ], [0, 1, 2, 3, 4]);
/// assert_eq!(arr[ .. 3], [0, 1, 2      ]);
/// assert_eq!(arr[ ..=3], [0, 1, 2, 3   ]); // This is a `RangeToInclusive`
/// assert_eq!(arr[1..  ], [   1, 2, 3, 4]);
/// assert_eq!(arr[1.. 3], [   1, 2      ]);
/// assert_eq!(arr[1..=3], [   1, 2, 3   ]);
/// ```
///
/// [slicing index]: crate::slice::SliceIndex
///
/// # Edition notes
///
/// It is planned that the syntax  `..=last` will construct this
/// type in a future edition, but it does not do so today.
#[lang = "RangeToInclusiveCopy"]
#[doc(alias = "..=")]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
pub struct RangeToInclusive<Idx> {
    /// The upper bound of the range (inclusive)
    #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
    pub last: Idx,
}

#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
impl<Idx: fmt::Debug> fmt::Debug for RangeToInclusive<Idx> {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(fmt, "..=")?;
        self.last.fmt(fmt)?;
        Ok(())
    }
}

impl<Idx: PartialOrd<Idx>> RangeToInclusive<Idx> {
    /// Returns `true` if `item` is contained in the range.
    ///
    /// # Examples
    ///
    /// ```
    /// assert!( (..=5).contains(&-1_000_000_000));
    /// assert!( (..=5).contains(&5));
    /// assert!(!(..=5).contains(&6));
    ///
    /// assert!( (..=1.0).contains(&1.0));
    /// assert!(!(..=1.0).contains(&f32::NAN));
    /// assert!(!(..=f32::NAN).contains(&0.5));
    /// ```
    #[inline]
    #[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
    #[rustc_const_unstable(feature = "const_range", issue = "none")]
    pub const fn contains<U>(&self, item: &U) -> bool
    where
        Idx: [const] PartialOrd<U>,
        U: ?Sized + [const] PartialOrd<Idx>,
    {
        <Self as RangeBounds<Idx>>::contains(self, item)
    }
}

#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
impl<T> From<legacy::RangeToInclusive<T>> for RangeToInclusive<T> {
    fn from(value: legacy::RangeToInclusive<T>) -> Self {
        Self { last: value.end }
    }
}
#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
impl<T> From<RangeToInclusive<T>> for legacy::RangeToInclusive<T> {
    fn from(value: RangeToInclusive<T>) -> Self {
        Self { end: value.last }
    }
}

// RangeToInclusive<Idx> cannot impl From<RangeTo<Idx>>
// because underflow would be possible with (..0).into()

#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> RangeBounds<T> for RangeToInclusive<T> {
    fn start_bound(&self) -> Bound<&T> {
        Unbounded
    }
    fn end_bound(&self) -> Bound<&T> {
        Included(&self.last)
    }
}

#[stable(feature = "new_range_to_inclusive_api", since = "1.96.0")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> RangeBounds<T> for RangeToInclusive<&T> {
    fn start_bound(&self) -> Bound<&T> {
        Unbounded
    }
    fn end_bound(&self) -> Bound<&T> {
        Included(self.last)
    }
}

#[unstable(feature = "range_into_bounds", issue = "136903")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> IntoBounds<T> for RangeToInclusive<T> {
    fn into_bounds(self) -> (Bound<T>, Bound<T>) {
        (Unbounded, Included(self.last))
    }
}

#[unstable(feature = "one_sided_range", issue = "69780")]
#[rustc_const_unstable(feature = "const_range", issue = "none")]
const impl<T> OneSidedRange<T> for RangeToInclusive<T>
where
    Self: RangeBounds<T>,
{
    fn bound(self) -> (OneSidedRangeBound, T) {
        (OneSidedRangeBound::EndInclusive, self.last)
    }
}
