diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs
index 78e27d73065aa..f19636fba5d95 100644
--- a/library/core/src/iter/range.rs
+++ b/library/core/src/iter/range.rs
@@ -1,4 +1,5 @@
 use crate::convert::TryFrom;
+use crate::marker::Destruct;
 use crate::mem;
 use crate::ops::{self, Try};
 
@@ -20,7 +21,8 @@ unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usi
 /// The *successor* operation moves towards values that compare greater.
 /// The *predecessor* operation moves towards values that compare lesser.
 #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-pub trait Step: Clone + PartialOrd + Sized {
+#[const_trait]
+pub trait Step: ~const Clone + ~const PartialOrd + Sized {
     /// Returns the number of *successor* steps required to get from `start` to `end`.
     ///
     /// Returns `None` if the number of steps would overflow `usize`
@@ -234,7 +236,8 @@ macro_rules! step_integer_impls {
         $(
             #[allow(unreachable_patterns)]
             #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-            impl Step for $u_narrower {
+            #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+            impl const Step for $u_narrower {
                 step_identical_methods!();
 
                 #[inline]
@@ -266,7 +269,8 @@ macro_rules! step_integer_impls {
 
             #[allow(unreachable_patterns)]
             #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-            impl Step for $i_narrower {
+            #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+            impl const Step for $i_narrower {
                 step_identical_methods!();
 
                 #[inline]
@@ -330,7 +334,8 @@ macro_rules! step_integer_impls {
         $(
             #[allow(unreachable_patterns)]
             #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-            impl Step for $u_wider {
+            #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+            impl const Step for $u_wider {
                 step_identical_methods!();
 
                 #[inline]
@@ -355,7 +360,8 @@ macro_rules! step_integer_impls {
 
             #[allow(unreachable_patterns)]
             #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-            impl Step for $i_wider {
+            #[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+            impl const Step for $i_wider {
                 step_identical_methods!();
 
                 #[inline]
@@ -405,7 +411,8 @@ step_integer_impls! {
 }
 
 #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
-impl Step for char {
+#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+impl const Step for char {
     #[inline]
     fn steps_between(&start: &char, &end: &char) -> Option<usize> {
         let start = start as u32;
@@ -423,6 +430,7 @@ impl Step for char {
     }
 
     #[inline]
+    #[rustc_allow_const_fn_unstable(const_try)]
     fn forward_checked(start: char, count: usize) -> Option<char> {
         let start = start as u32;
         let mut res = Step::forward_checked(start, count)?;
@@ -439,6 +447,7 @@ impl Step for char {
     }
 
     #[inline]
+    #[rustc_allow_const_fn_unstable(const_try)]
     fn backward_checked(start: char, count: usize) -> Option<char> {
         let start = start as u32;
         let mut res = Step::backward_checked(start, count)?;
@@ -514,6 +523,7 @@ macro_rules! range_incl_exact_iter_impl {
 }
 
 /// Specialization implementations for `Range`.
+#[const_trait]
 trait RangeIteratorImpl {
     type Item;
 
@@ -528,7 +538,7 @@ trait RangeIteratorImpl {
     fn spec_advance_back_by(&mut self, n: usize) -> Result<(), usize>;
 }
 
-impl<A: Step> RangeIteratorImpl for ops::Range<A> {
+impl<A: ~const Step + ~const Destruct> const RangeIteratorImpl for ops::Range<A> {
     type Item = A;
 
     #[inline]
@@ -614,7 +624,7 @@ impl<A: Step> RangeIteratorImpl for ops::Range<A> {
     }
 }
 
-impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
+impl<T: ~const TrustedStep + ~const Destruct> const RangeIteratorImpl for ops::Range<T> {
     #[inline]
     fn spec_next(&mut self) -> Option<T> {
         if self.start < self.end {
@@ -702,7 +712,8 @@ impl<T: TrustedStep> RangeIteratorImpl for ops::Range<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Step> Iterator for ops::Range<A> {
+#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+impl<A: ~const Step + ~const Destruct> const Iterator for ops::Range<A> {
     type Item = A;
 
     #[inline]
@@ -812,7 +823,8 @@ range_incl_exact_iter_impl! {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Step> DoubleEndedIterator for ops::Range<A> {
+#[rustc_const_unstable(feature = "const_iter", issue = "92476")]
+impl<A: ~const Step + ~const Destruct> const DoubleEndedIterator for ops::Range<A> {
     #[inline]
     fn next_back(&mut self) -> Option<A> {
         self.spec_next_back()
diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs
index ed23873cdde7c..7a10dea500a96 100644
--- a/library/core/src/iter/traits/double_ended.rs
+++ b/library/core/src/iter/traits/double_ended.rs
@@ -1,3 +1,4 @@
+use crate::marker::Destruct;
 use crate::ops::{ControlFlow, Try};
 
 /// An iterator able to yield elements from both ends.
@@ -37,6 +38,7 @@ use crate::ops::{ControlFlow, Try};
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "DoubleEndedIterator")]
+#[const_trait]
 pub trait DoubleEndedIterator: Iterator {
     /// Removes and returns an element from the end of the iterator.
     ///
@@ -131,7 +133,10 @@ pub trait DoubleEndedIterator: Iterator {
     /// [`Err(k)`]: Err
     #[inline]
     #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
-    fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+    fn advance_back_by(&mut self, n: usize) -> Result<(), usize>
+    where
+        Self::Item: ~const Destruct,
+    {
         for i in 0..n {
             self.next_back().ok_or(i)?;
         }
@@ -181,6 +186,7 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_nth_back", since = "1.37.0")]
+    #[rustc_do_not_const_check]
     fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
         self.advance_back_by(n).ok()?;
         self.next_back()
@@ -218,6 +224,7 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iterator_try_fold", since = "1.27.0")]
+    #[rustc_do_not_const_check]
     fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
     where
         Self: Sized,
@@ -289,6 +296,7 @@ pub trait DoubleEndedIterator: Iterator {
     #[doc(alias = "foldr")]
     #[inline]
     #[stable(feature = "iter_rfold", since = "1.27.0")]
+    #[rustc_do_not_const_check]
     fn rfold<B, F>(mut self, init: B, mut f: F) -> B
     where
         Self: Sized,
@@ -344,6 +352,7 @@ pub trait DoubleEndedIterator: Iterator {
     /// ```
     #[inline]
     #[stable(feature = "iter_rfind", since = "1.27.0")]
+    #[rustc_do_not_const_check]
     fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
     where
         Self: Sized,
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index d48760ab3ebfa..6fc86550b63e7 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1,5 +1,6 @@
 use crate::array;
 use crate::cmp::{self, Ordering};
+use crate::marker::Destruct;
 use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
 
 use super::super::try_process;
@@ -336,8 +337,10 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
-    #[rustc_do_not_const_check]
-    fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+    fn advance_by(&mut self, n: usize) -> Result<(), usize>
+    where
+        Self::Item: ~const Destruct,
+    {
         for i in 0..n {
             self.next().ok_or(i)?;
         }
@@ -385,8 +388,10 @@ pub trait Iterator {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_do_not_const_check]
-    fn nth(&mut self, n: usize) -> Option<Self::Item> {
+    fn nth(&mut self, n: usize) -> Option<Self::Item>
+    where
+        Self::Item: ~const Destruct,
+    {
         self.advance_by(n).ok()?;
         self.next()
     }
diff --git a/library/core/src/iter/traits/marker.rs b/library/core/src/iter/traits/marker.rs
index af02848233d99..c8f60defff771 100644
--- a/library/core/src/iter/traits/marker.rs
+++ b/library/core/src/iter/traits/marker.rs
@@ -86,4 +86,5 @@ pub unsafe trait InPlaceIterable: Iterator {}
 /// for details. Consumers are free to rely on the invariants in unsafe code.
 #[unstable(feature = "trusted_step", issue = "85731")]
 #[rustc_specialization_trait]
-pub unsafe trait TrustedStep: Step {}
+#[const_trait]
+pub unsafe trait TrustedStep: ~const Step {}
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 526232f44ee1e..1076d357070ef 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -123,9 +123,11 @@
 #![feature(const_index_range_slice_index)]
 #![feature(const_inherent_unchecked_arith)]
 #![feature(const_int_unchecked_arith)]
+#![feature(const_intoiterator_identity)]
 #![feature(const_intrinsic_forget)]
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
+#![feature(const_iter)]
 #![feature(const_likely)]
 #![feature(const_maybe_uninit_uninit_array)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
diff --git a/library/core/tests/iter/consts.rs b/library/core/tests/iter/consts.rs
new file mode 100644
index 0000000000000..d56687e48c96a
--- /dev/null
+++ b/library/core/tests/iter/consts.rs
@@ -0,0 +1,36 @@
+#[test]
+fn const_manual_iter() {
+    struct S(bool);
+
+    impl const Iterator for S {
+        type Item = ();
+
+        fn next(&mut self) -> Option<Self::Item> {
+            if self.0 == false {
+                self.0 = true;
+                Some(())
+            } else {
+                None
+            }
+        }
+    }
+    const {
+        let mut val = S(false);
+        assert!(val.next().is_some());
+        assert!(val.next().is_none());
+        assert!(val.next().is_none());
+    }
+}
+
+#[test]
+fn const_range() {
+    const {
+        let mut arr = [0; 3];
+        for i in 0..arr.len() {
+            arr[i] = i;
+        }
+        assert!(arr[0] == 0);
+        assert!(arr[1] == 1);
+        assert!(arr[2] == 2);
+    }
+}
diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs
index 770b6f7601fa2..cbb18e79e2d43 100644
--- a/library/core/tests/iter/mod.rs
+++ b/library/core/tests/iter/mod.rs
@@ -20,6 +20,8 @@ mod range;
 mod sources;
 mod traits;
 
+mod consts;
+
 use core::cell::Cell;
 use core::convert::TryFrom;
 use core::iter::*;
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index ccb7be68eb1b2..637cc6e9f629b 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -12,8 +12,11 @@
 #![feature(const_caller_location)]
 #![feature(const_cell_into_inner)]
 #![feature(const_convert)]
+#![feature(const_for)]
 #![feature(const_hash)]
 #![feature(const_heap)]
+#![feature(const_intoiterator_identity)]
+#![feature(const_iter)]
 #![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init_read)]
 #![feature(const_nonnull_new)]
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs
index a450dbb82d1bd..e6f7dc410b614 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.rs
+++ b/tests/ui/typeck/typeck_type_placeholder_item.rs
@@ -228,5 +228,4 @@ fn evens_squared(n: usize) -> _ {
 
 const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
 //~^ ERROR the trait bound
-//~| ERROR the trait bound
 //~| ERROR the placeholder
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr
index bc6c9fd077993..9144ab9e3a6bd 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr
@@ -437,19 +437,6 @@ LL | fn evens_squared(n: usize) -> _ {
    |                               not allowed in type signatures
    |                               help: replace with an appropriate return type: `impl Iterator<Item = usize>`
 
-error[E0277]: the trait bound `std::ops::Range<{integer}>: Iterator` is not satisfied
-  --> $DIR/typeck_type_placeholder_item.rs:229:22
-   |
-LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
-   |                      ^^^^^^ `std::ops::Range<{integer}>` is not an iterator
-   |
-   = help: the trait `~const Iterator` is not implemented for `std::ops::Range<{integer}>`
-note: the trait `Iterator` is implemented for `std::ops::Range<{integer}>`, but that implementation is not `const`
-  --> $DIR/typeck_type_placeholder_item.rs:229:14
-   |
-LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
-   |              ^^^^^^^
-
 error[E0277]: the trait bound `Filter<std::ops::Range<{integer}>, [closure@$DIR/typeck_type_placeholder_item.rs:229:29: 229:32]>: Iterator` is not satisfied
   --> $DIR/typeck_type_placeholder_item.rs:229:45
    |
@@ -677,7 +664,7 @@ LL |     const D: _ = 42;
    |              not allowed in type signatures
    |              help: replace with the correct type: `i32`
 
-error: aborting due to 73 previous errors
+error: aborting due to 72 previous errors
 
 Some errors have detailed explanations: E0121, E0277, E0282, E0403.
 For more information about an error, try `rustc --explain E0121`.