summaryrefslogtreecommitdiffstats
path: root/library/core/src/ops
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--library/core/src/ops/arith.rs50
-rw-r--r--library/core/src/ops/bit.rs11
-rw-r--r--library/core/src/ops/control_flow.rs9
-rw-r--r--library/core/src/ops/deref.rs2
-rw-r--r--library/core/src/ops/drop.rs3
-rw-r--r--library/core/src/ops/function.rs28
-rw-r--r--library/core/src/ops/generator.rs1
-rw-r--r--library/core/src/ops/index.rs2
-rw-r--r--library/core/src/ops/index_range.rs171
-rw-r--r--library/core/src/ops/mod.rs3
-rw-r--r--library/core/src/ops/range.rs2
-rw-r--r--library/core/src/ops/try_trait.rs36
12 files changed, 256 insertions, 62 deletions
diff --git a/library/core/src/ops/arith.rs b/library/core/src/ops/arith.rs
index e367be8c1..75c52d3ec 100644
--- a/library/core/src/ops/arith.rs
+++ b/library/core/src/ops/arith.rs
@@ -65,38 +65,15 @@
/// ```
#[lang = "add"]
#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(
- bootstrap,
- rustc_on_unimplemented(
- on(
- all(_Self = "{integer}", Rhs = "{float}"),
- message = "cannot add a float to an integer",
- ),
- on(
- all(_Self = "{float}", Rhs = "{integer}"),
- message = "cannot add an integer to a float",
- ),
- message = "cannot add `{Rhs}` to `{Self}`",
- label = "no implementation for `{Self} + {Rhs}`"
- )
-)]
-#[cfg_attr(
- not(bootstrap),
- rustc_on_unimplemented(
- on(
- all(_Self = "{integer}", Rhs = "{float}"),
- message = "cannot add a float to an integer",
- ),
- on(
- all(_Self = "{float}", Rhs = "{integer}"),
- message = "cannot add an integer to a float",
- ),
- message = "cannot add `{Rhs}` to `{Self}`",
- label = "no implementation for `{Self} + {Rhs}`",
- append_const_msg,
- )
+#[rustc_on_unimplemented(
+ on(all(_Self = "{integer}", Rhs = "{float}"), message = "cannot add a float to an integer",),
+ on(all(_Self = "{float}", Rhs = "{integer}"), message = "cannot add an integer to a float",),
+ message = "cannot add `{Rhs}` to `{Self}`",
+ label = "no implementation for `{Self} + {Rhs}`",
+ append_const_msg
)]
#[doc(alias = "+")]
+#[const_trait]
pub trait Add<Rhs = Self> {
/// The resulting type after applying the `+` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -201,9 +178,11 @@ add_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
message = "cannot subtract `{Rhs}` from `{Self}`",
- label = "no implementation for `{Self} - {Rhs}`"
+ label = "no implementation for `{Self} - {Rhs}`",
+ append_const_msg
)]
#[doc(alias = "-")]
+#[const_trait]
pub trait Sub<Rhs = Self> {
/// The resulting type after applying the `-` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -333,6 +312,7 @@ sub_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
label = "no implementation for `{Self} * {Rhs}`"
)]
#[doc(alias = "*")]
+#[const_trait]
pub trait Mul<Rhs = Self> {
/// The resulting type after applying the `*` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -466,6 +446,7 @@ mul_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
label = "no implementation for `{Self} / {Rhs}`"
)]
#[doc(alias = "/")]
+#[const_trait]
pub trait Div<Rhs = Self> {
/// The resulting type after applying the `/` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -568,6 +549,7 @@ div_impl_float! { f32 f64 }
label = "no implementation for `{Self} % {Rhs}`"
)]
#[doc(alias = "%")]
+#[const_trait]
pub trait Rem<Rhs = Self> {
/// The resulting type after applying the `%` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -682,6 +664,7 @@ rem_impl_float! { f32 f64 }
#[lang = "neg"]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "-")]
+#[const_trait]
pub trait Neg {
/// The resulting type after applying the `-` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -755,6 +738,7 @@ neg_impl! { isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "+")]
#[doc(alias = "+=")]
+#[const_trait]
pub trait AddAssign<Rhs = Self> {
/// Performs the `+=` operation.
///
@@ -822,6 +806,7 @@ add_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "-")]
#[doc(alias = "-=")]
+#[const_trait]
pub trait SubAssign<Rhs = Self> {
/// Performs the `-=` operation.
///
@@ -880,6 +865,7 @@ sub_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "*")]
#[doc(alias = "*=")]
+#[const_trait]
pub trait MulAssign<Rhs = Self> {
/// Performs the `*=` operation.
///
@@ -938,6 +924,7 @@ mul_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "/")]
#[doc(alias = "/=")]
+#[const_trait]
pub trait DivAssign<Rhs = Self> {
/// Performs the `/=` operation.
///
@@ -999,6 +986,7 @@ div_assign_impl! { usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 f32 f64 }
)]
#[doc(alias = "%")]
#[doc(alias = "%=")]
+#[const_trait]
pub trait RemAssign<Rhs = Self> {
/// Performs the `%=` operation.
///
diff --git a/library/core/src/ops/bit.rs b/library/core/src/ops/bit.rs
index 7c664226f..327009801 100644
--- a/library/core/src/ops/bit.rs
+++ b/library/core/src/ops/bit.rs
@@ -31,6 +31,7 @@
#[lang = "not"]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(alias = "!")]
+#[const_trait]
pub trait Not {
/// The resulting type after applying the `!` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -143,6 +144,7 @@ impl const Not for ! {
message = "no implementation for `{Self} & {Rhs}`",
label = "no implementation for `{Self} & {Rhs}`"
)]
+#[const_trait]
pub trait BitAnd<Rhs = Self> {
/// The resulting type after applying the `&` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -244,6 +246,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} | {Rhs}`",
label = "no implementation for `{Self} | {Rhs}`"
)]
+#[const_trait]
pub trait BitOr<Rhs = Self> {
/// The resulting type after applying the `|` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -345,6 +348,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} ^ {Rhs}`",
label = "no implementation for `{Self} ^ {Rhs}`"
)]
+#[const_trait]
pub trait BitXor<Rhs = Self> {
/// The resulting type after applying the `^` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -445,6 +449,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} << {Rhs}`",
label = "no implementation for `{Self} << {Rhs}`"
)]
+#[const_trait]
pub trait Shl<Rhs = Self> {
/// The resulting type after applying the `<<` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -564,6 +569,7 @@ shl_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 isize i128 }
message = "no implementation for `{Self} >> {Rhs}`",
label = "no implementation for `{Self} >> {Rhs}`"
)]
+#[const_trait]
pub trait Shr<Rhs = Self> {
/// The resulting type after applying the `>>` operator.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -692,6 +698,7 @@ shr_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
message = "no implementation for `{Self} &= {Rhs}`",
label = "no implementation for `{Self} &= {Rhs}`"
)]
+#[const_trait]
pub trait BitAndAssign<Rhs = Self> {
/// Performs the `&=` operation.
///
@@ -764,6 +771,7 @@ bitand_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} |= {Rhs}`",
label = "no implementation for `{Self} |= {Rhs}`"
)]
+#[const_trait]
pub trait BitOrAssign<Rhs = Self> {
/// Performs the `|=` operation.
///
@@ -836,6 +844,7 @@ bitor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} ^= {Rhs}`",
label = "no implementation for `{Self} ^= {Rhs}`"
)]
+#[const_trait]
pub trait BitXorAssign<Rhs = Self> {
/// Performs the `^=` operation.
///
@@ -906,6 +915,7 @@ bitxor_assign_impl! { bool usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 }
message = "no implementation for `{Self} <<= {Rhs}`",
label = "no implementation for `{Self} <<= {Rhs}`"
)]
+#[const_trait]
pub trait ShlAssign<Rhs = Self> {
/// Performs the `<<=` operation.
///
@@ -989,6 +999,7 @@ shl_assign_impl_all! { u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize }
message = "no implementation for `{Self} >>= {Rhs}`",
label = "no implementation for `{Self} >>= {Rhs}`"
)]
+#[const_trait]
pub trait ShrAssign<Rhs = Self> {
/// Performs the `>>=` operation.
///
diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs
index b1f5559dc..72ebe653c 100644
--- a/library/core/src/ops/control_flow.rs
+++ b/library/core/src/ops/control_flow.rs
@@ -95,7 +95,8 @@ pub enum ControlFlow<B, C = ()> {
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<B, C> ops::Try for ControlFlow<B, C> {
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<B, C> const ops::Try for ControlFlow<B, C> {
type Output = C;
type Residual = ControlFlow<B, convert::Infallible>;
@@ -114,7 +115,8 @@ impl<B, C> ops::Try for ControlFlow<B, C> {
}
#[unstable(feature = "try_trait_v2", issue = "84277")]
-impl<B, C> ops::FromResidual for ControlFlow<B, C> {
+#[rustc_const_unstable(feature = "const_convert", issue = "88674")]
+impl<B, C> const ops::FromResidual for ControlFlow<B, C> {
#[inline]
fn from_residual(residual: ControlFlow<B, convert::Infallible>) -> Self {
match residual {
@@ -124,7 +126,8 @@ impl<B, C> ops::FromResidual for ControlFlow<B, C> {
}
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
-impl<B, C> ops::Residual<C> for ControlFlow<B, convert::Infallible> {
+#[rustc_const_unstable(feature = "const_try", issue = "74935")]
+impl<B, C> const ops::Residual<C> for ControlFlow<B, convert::Infallible> {
type TryType = ControlFlow<B, C>;
}
diff --git a/library/core/src/ops/deref.rs b/library/core/src/ops/deref.rs
index d68932402..4f4c99c4a 100644
--- a/library/core/src/ops/deref.rs
+++ b/library/core/src/ops/deref.rs
@@ -61,6 +61,7 @@
#[doc(alias = "&*")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "Deref"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait Deref {
/// The resulting type after dereferencing.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -169,6 +170,7 @@ impl<T: ?Sized> const Deref for &mut T {
#[lang = "deref_mut"]
#[doc(alias = "*")]
#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
pub trait DerefMut: Deref {
/// Mutably dereferences the value.
#[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/ops/drop.rs b/library/core/src/ops/drop.rs
index aa654aa55..a2c3d978c 100644
--- a/library/core/src/ops/drop.rs
+++ b/library/core/src/ops/drop.rs
@@ -134,6 +134,7 @@
/// these types cannot have destructors.
#[lang = "drop"]
#[stable(feature = "rust1", since = "1.0.0")]
+#[const_trait]
pub trait Drop {
/// Executes the destructor for this type.
///
@@ -156,7 +157,7 @@ pub trait Drop {
/// handled by the compiler, but when using unsafe code, can sometimes occur
/// unintentionally, particularly when using [`ptr::drop_in_place`].
///
- /// [E0040]: ../../error-index.html#E0040
+ /// [E0040]: ../../error_codes/E0040.html
/// [`panic!`]: crate::panic!
/// [`mem::drop`]: drop
/// [`ptr::drop_in_place`]: crate::ptr::drop_in_place
diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs
index c5a194b7d..2e0a752c8 100644
--- a/library/core/src/ops/function.rs
+++ b/library/core/src/ops/function.rs
@@ -71,6 +71,7 @@
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait Fn<Args>: FnMut<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -158,6 +159,7 @@ pub trait Fn<Args>: FnMut<Args> {
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait FnMut<Args>: FnOnce<Args> {
/// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -237,6 +239,7 @@ pub trait FnMut<Args>: FnOnce<Args> {
)]
#[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait FnOnce<Args> {
/// The returned type after the call operator is used.
#[lang = "fn_once_output"]
@@ -250,9 +253,10 @@ pub trait FnOnce<Args> {
mod impls {
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A, F: ?Sized> Fn<A> for &F
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A, F: ?Sized> const Fn<A> for &F
where
- F: Fn<A>,
+ F: ~const Fn<A>,
{
extern "rust-call" fn call(&self, args: A) -> F::Output {
(**self).call(args)
@@ -260,9 +264,10 @@ mod impls {
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A, F: ?Sized> FnMut<A> for &F
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A, F: ?Sized> const FnMut<A> for &F
where
- F: Fn<A>,
+ F: ~const Fn<A>,
{
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
(**self).call(args)
@@ -270,9 +275,10 @@ mod impls {
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A, F: ?Sized> FnOnce<A> for &F
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A, F: ?Sized> const FnOnce<A> for &F
where
- F: Fn<A>,
+ F: ~const Fn<A>,
{
type Output = F::Output;
@@ -282,9 +288,10 @@ mod impls {
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A, F: ?Sized> FnMut<A> for &mut F
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A, F: ?Sized> const FnMut<A> for &mut F
where
- F: FnMut<A>,
+ F: ~const FnMut<A>,
{
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
(*self).call_mut(args)
@@ -292,9 +299,10 @@ mod impls {
}
#[stable(feature = "rust1", since = "1.0.0")]
- impl<A, F: ?Sized> FnOnce<A> for &mut F
+ #[rustc_const_unstable(feature = "const_fn_trait_ref_impls", issue = "101803")]
+ impl<A, F: ?Sized> const FnOnce<A> for &mut F
where
- F: FnMut<A>,
+ F: ~const FnMut<A>,
{
type Output = F::Output;
extern "rust-call" fn call_once(self, args: A) -> F::Output {
diff --git a/library/core/src/ops/generator.rs b/library/core/src/ops/generator.rs
index b651b7b23..fee4beb1e 100644
--- a/library/core/src/ops/generator.rs
+++ b/library/core/src/ops/generator.rs
@@ -83,7 +83,6 @@ pub trait Generator<R = ()> {
/// `return` statement or implicitly as the last expression of a generator
/// literal. For example futures would use this as `Result<T, E>` as it
/// represents a completed future.
- #[lang = "generator_return"]
type Return;
/// Resumes the execution of this generator.
diff --git a/library/core/src/ops/index.rs b/library/core/src/ops/index.rs
index e2e569cb7..dd4e3ac1c 100644
--- a/library/core/src/ops/index.rs
+++ b/library/core/src/ops/index.rs
@@ -55,6 +55,7 @@
#[doc(alias = "]")]
#[doc(alias = "[")]
#[doc(alias = "[]")]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait Index<Idx: ?Sized> {
/// The returned type after indexing.
#[stable(feature = "rust1", since = "1.0.0")]
@@ -163,6 +164,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
#[doc(alias = "[")]
#[doc(alias = "]")]
#[doc(alias = "[]")]
+#[cfg_attr(not(bootstrap), const_trait)]
pub trait IndexMut<Idx: ?Sized>: Index<Idx> {
/// Performs the mutable indexing (`container[index]`) operation.
///
diff --git a/library/core/src/ops/index_range.rs b/library/core/src/ops/index_range.rs
new file mode 100644
index 000000000..3e06776d2
--- /dev/null
+++ b/library/core/src/ops/index_range.rs
@@ -0,0 +1,171 @@
+use crate::intrinsics::{assert_unsafe_precondition, unchecked_add, unchecked_sub};
+use crate::iter::{FusedIterator, TrustedLen};
+
+/// Like a `Range<usize>`, but with a safety invariant that `start <= end`.
+///
+/// This means that `end - start` cannot overflow, allowing some μoptimizations.
+///
+/// (Normal `Range` code needs to handle degenerate ranges like `10..0`,
+/// which takes extra checks compared to only handling the canonical form.)
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub(crate) struct IndexRange {
+ start: usize,
+ end: usize,
+}
+
+impl IndexRange {
+ /// # Safety
+ /// - `start <= end`
+ #[inline]
+ pub const unsafe fn new_unchecked(start: usize, end: usize) -> Self {
+ // SAFETY: comparisons on usize are pure
+ unsafe {
+ assert_unsafe_precondition!(
+ "IndexRange::new_unchecked requires `start <= end`",
+ (start: usize, end: usize) => start <= end
+ )
+ };
+ IndexRange { start, end }
+ }
+
+ #[inline]
+ pub const fn zero_to(end: usize) -> Self {
+ IndexRange { start: 0, end }
+ }
+
+ #[inline]
+ pub const fn start(&self) -> usize {
+ self.start
+ }
+
+ #[inline]
+ pub const fn end(&self) -> usize {
+ self.end
+ }
+
+ #[inline]
+ pub const fn len(&self) -> usize {
+ // SAFETY: By invariant, this cannot wrap
+ unsafe { unchecked_sub(self.end, self.start) }
+ }
+
+ /// # Safety
+ /// - Can only be called when `start < end`, aka when `len > 0`.
+ #[inline]
+ unsafe fn next_unchecked(&mut self) -> usize {
+ debug_assert!(self.start < self.end);
+
+ let value = self.start;
+ // SAFETY: The range isn't empty, so this cannot overflow
+ self.start = unsafe { unchecked_add(value, 1) };
+ value
+ }
+
+ /// # Safety
+ /// - Can only be called when `start < end`, aka when `len > 0`.
+ #[inline]
+ unsafe fn next_back_unchecked(&mut self) -> usize {
+ debug_assert!(self.start < self.end);
+
+ // SAFETY: The range isn't empty, so this cannot overflow
+ let value = unsafe { unchecked_sub(self.end, 1) };
+ self.end = value;
+ value
+ }
+
+ /// Removes the first `n` items from this range, returning them as an `IndexRange`.
+ /// If there are fewer than `n`, then the whole range is returned and
+ /// `self` is left empty.
+ ///
+ /// This is designed to help implement `Iterator::advance_by`.
+ #[inline]
+ pub fn take_prefix(&mut self, n: usize) -> Self {
+ let mid = if n <= self.len() {
+ // SAFETY: We just checked that this will be between start and end,
+ // and thus the addition cannot overflow.
+ unsafe { unchecked_add(self.start, n) }
+ } else {
+ self.end
+ };
+ let prefix = Self { start: self.start, end: mid };
+ self.start = mid;
+ prefix
+ }
+
+ /// Removes the last `n` items from this range, returning them as an `IndexRange`.
+ /// If there are fewer than `n`, then the whole range is returned and
+ /// `self` is left empty.
+ ///
+ /// This is designed to help implement `Iterator::advance_back_by`.
+ #[inline]
+ pub fn take_suffix(&mut self, n: usize) -> Self {
+ let mid = if n <= self.len() {
+ // SAFETY: We just checked that this will be between start and end,
+ // and thus the addition cannot overflow.
+ unsafe { unchecked_sub(self.end, n) }
+ } else {
+ self.start
+ };
+ let suffix = Self { start: mid, end: self.end };
+ self.end = mid;
+ suffix
+ }
+}
+
+impl Iterator for IndexRange {
+ type Item = usize;
+
+ #[inline]
+ fn next(&mut self) -> Option<usize> {
+ if self.len() > 0 {
+ // SAFETY: We just checked that the range is non-empty
+ unsafe { Some(self.next_unchecked()) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.len();
+ (len, Some(len))
+ }
+
+ #[inline]
+ fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+ let original_len = self.len();
+ self.take_prefix(n);
+ if n > original_len { Err(original_len) } else { Ok(()) }
+ }
+}
+
+impl DoubleEndedIterator for IndexRange {
+ #[inline]
+ fn next_back(&mut self) -> Option<usize> {
+ if self.len() > 0 {
+ // SAFETY: We just checked that the range is non-empty
+ unsafe { Some(self.next_back_unchecked()) }
+ } else {
+ None
+ }
+ }
+
+ #[inline]
+ fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+ let original_len = self.len();
+ self.take_suffix(n);
+ if n > original_len { Err(original_len) } else { Ok(()) }
+ }
+}
+
+impl ExactSizeIterator for IndexRange {
+ #[inline]
+ fn len(&self) -> usize {
+ self.len()
+ }
+}
+
+// SAFETY: Because we only deal in `usize`, our `len` is always perfect.
+unsafe impl TrustedLen for IndexRange {}
+
+impl FusedIterator for IndexRange {}
diff --git a/library/core/src/ops/mod.rs b/library/core/src/ops/mod.rs
index 31c1a1d09..a5e5b13b3 100644
--- a/library/core/src/ops/mod.rs
+++ b/library/core/src/ops/mod.rs
@@ -146,6 +146,7 @@ mod drop;
mod function;
mod generator;
mod index;
+mod index_range;
mod range;
mod try_trait;
mod unsize;
@@ -178,6 +179,8 @@ pub use self::index::{Index, IndexMut};
#[stable(feature = "rust1", since = "1.0.0")]
pub use self::range::{Range, RangeFrom, RangeFull, RangeTo};
+pub(crate) use self::index_range::IndexRange;
+
#[stable(feature = "inclusive_range", since = "1.26.0")]
pub use self::range::{Bound, RangeBounds, RangeInclusive, RangeToInclusive};
diff --git a/library/core/src/ops/range.rs b/library/core/src/ops/range.rs
index a3b148473..d29ae3561 100644
--- a/library/core/src/ops/range.rs
+++ b/library/core/src/ops/range.rs
@@ -677,7 +677,7 @@ pub enum Bound<T> {
impl<T> Bound<T> {
/// Converts from `&Bound<T>` to `Bound<&T>`.
#[inline]
- #[unstable(feature = "bound_as_ref", issue = "80996")]
+ #[stable(feature = "bound_as_ref_shared", since = "1.65.0")]
pub fn as_ref(&self) -> Bound<&T> {
match *self {
Included(ref x) => Included(x),
diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs
index 02f7f62bf..84a690468 100644
--- a/library/core/src/ops/try_trait.rs
+++ b/library/core/src/ops/try_trait.rs
@@ -128,7 +128,8 @@ use crate::ops::ControlFlow;
)]
#[doc(alias = "?")]
#[lang = "Try"]
-pub trait Try: FromResidual {
+#[const_trait]
+pub trait Try: ~const FromResidual {
/// The type of the value produced by `?` when *not* short-circuiting.
#[unstable(feature = "try_trait_v2", issue = "84277")]
type Output;
@@ -232,7 +233,7 @@ pub trait Try: FromResidual {
message = "the `?` operator can only be used on `Result`s, not `Option`s, \
in {ItemContext} that returns `Result`",
label = "use `.ok_or(...)?` to provide an error compatible with `{Self}`",
- enclosing_scope = "this function returns a `Result`"
+ parent_label = "this function returns a `Result`"
),
on(
all(
@@ -245,7 +246,7 @@ pub trait Try: FromResidual {
message = "the `?` operator can only be used on `Result`s \
in {ItemContext} that returns `Result`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
- enclosing_scope = "this function returns a `Result`"
+ parent_label = "this function returns a `Result`"
),
on(
all(
@@ -256,7 +257,7 @@ pub trait Try: FromResidual {
message = "the `?` operator can only be used on `Option`s, not `Result`s, \
in {ItemContext} that returns `Option`",
label = "use `.ok()?` if you want to discard the `{R}` error information",
- enclosing_scope = "this function returns an `Option`"
+ parent_label = "this function returns an `Option`"
),
on(
all(
@@ -268,7 +269,7 @@ pub trait Try: FromResidual {
message = "the `?` operator can only be used on `Option`s \
in {ItemContext} that returns `Option`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
- enclosing_scope = "this function returns an `Option`"
+ parent_label = "this function returns an `Option`"
),
on(
all(
@@ -279,7 +280,7 @@ pub trait Try: FromResidual {
message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
- enclosing_scope = "this function returns a `ControlFlow`",
+ parent_label = "this function returns a `ControlFlow`",
note = "unlike `Result`, there's no `From`-conversion performed for `ControlFlow`"
),
on(
@@ -291,7 +292,7 @@ pub trait Try: FromResidual {
message = "the `?` operator can only be used on `ControlFlow`s \
in {ItemContext} that returns `ControlFlow`",
label = "this `?` produces `{R}`, which is incompatible with `{Self}`",
- enclosing_scope = "this function returns a `ControlFlow`",
+ parent_label = "this function returns a `ControlFlow`",
),
on(
all(from_desugaring = "QuestionMark"),
@@ -299,11 +300,12 @@ pub trait Try: FromResidual {
that returns `Result` or `Option` \
(or another type that implements `{FromResidual}`)",
label = "cannot use the `?` operator in {ItemContext} that returns `{Self}`",
- enclosing_scope = "this function should return `Result` or `Option` to accept `?`"
+ parent_label = "this function should return `Result` or `Option` to accept `?`"
),
)]
#[rustc_diagnostic_item = "FromResidual"]
#[unstable(feature = "try_trait_v2", issue = "84277")]
+#[const_trait]
pub trait FromResidual<R = <Self as Try>::Residual> {
/// Constructs the type from a compatible `Residual` type.
///
@@ -356,10 +358,11 @@ where
/// and in the other direction,
/// `<Result<Infallible, E> as Residual<T>>::TryType = Result<T, E>`.
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
+#[const_trait]
pub trait Residual<O> {
/// The "return" type of this meta-function.
#[unstable(feature = "try_trait_v2_residual", issue = "91285")]
- type TryType: Try<Output = O, Residual = Self>;
+ type TryType: ~const Try<Output = O, Residual = Self>;
}
#[unstable(feature = "pub_crate_should_not_need_unstable_attr", issue = "none")]
@@ -376,16 +379,19 @@ pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::
pub(crate) struct NeverShortCircuit<T>(pub T);
impl<T> NeverShortCircuit<T> {
- /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`.
+ /// Implementation for building `ConstFnMutClosure` for wrapping the output of a ~const FnMut in a `NeverShortCircuit`.
#[inline]
- pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
- move |a, b| NeverShortCircuit(f(a, b))
+ pub const fn wrap_mut_2_imp<A, B, F: ~const FnMut(A, B) -> T>(
+ f: &mut F,
+ (a, b): (A, B),
+ ) -> NeverShortCircuit<T> {
+ NeverShortCircuit(f(a, b))
}
}
pub(crate) enum NeverShortCircuitResidual {}
-impl<T> Try for NeverShortCircuit<T> {
+impl<T> const Try for NeverShortCircuit<T> {
type Output = T;
type Residual = NeverShortCircuitResidual;
@@ -400,14 +406,14 @@ impl<T> Try for NeverShortCircuit<T> {
}
}
-impl<T> FromResidual for NeverShortCircuit<T> {
+impl<T> const FromResidual for NeverShortCircuit<T> {
#[inline]
fn from_residual(never: NeverShortCircuitResidual) -> Self {
match never {}
}
}
-impl<T> Residual<T> for NeverShortCircuitResidual {
+impl<T> const Residual<T> for NeverShortCircuitResidual {
type TryType = NeverShortCircuit<T>;
}