diff --git a/library/core/src/iter/range.rs b/library/core/src/iter/range.rs index e6acf3081c890..331c367314e63 100644 --- a/library/core/src/iter/range.rs +++ b/library/core/src/iter/range.rs @@ -2,6 +2,7 @@ use super::{ FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, TrustedStep, }; use crate::ascii::Char as AsciiChar; +use crate::marker::Destruct; use crate::mem; use crate::net::{Ipv4Addr, Ipv6Addr}; use crate::num::NonZero; @@ -1000,7 +1001,7 @@ macro_rules! range_incl_exact_iter_impl { } /// Specialization implementations for `Range`. -trait RangeIteratorImpl { +const trait RangeIteratorImpl { type Item; // Iterator @@ -1014,7 +1015,8 @@ trait RangeIteratorImpl { fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZero>; } -impl RangeIteratorImpl for ops::Range { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +const impl RangeIteratorImpl for ops::Range { type Item = A; #[inline] @@ -1094,7 +1096,8 @@ impl RangeIteratorImpl for ops::Range { } } -impl RangeIteratorImpl for ops::Range { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +const impl RangeIteratorImpl for ops::Range { #[inline] fn spec_next(&mut self) -> Option { if self.start < self.end { @@ -1177,7 +1180,8 @@ impl RangeIteratorImpl for ops::Range { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for ops::Range { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +const impl Iterator for ops::Range { type Item = A; #[inline] @@ -1230,7 +1234,10 @@ impl Iterator for ops::Range { } #[inline] - fn is_sorted(self) -> bool { + fn is_sorted(self) -> bool + where + Self: [const] Destruct, + { true } @@ -1310,7 +1317,8 @@ range_incl_exact_iter_impl! { } #[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for ops::Range { +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +const impl DoubleEndedIterator for ops::Range { #[inline] fn next_back(&mut self) -> Option { 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 3df765c3da709..a7c8ec9319a07 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -185,8 +185,10 @@ pub const trait DoubleEndedIterator: [const] Iterator { /// [`Err(k)`]: Err #[inline] #[unstable(feature = "iter_advance_by", issue = "77404")] - #[rustc_non_const_trait_method] - fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + fn advance_back_by(&mut self, n: usize) -> Result<(), NonZero> + where + Self::Item: [const] Destruct, + { for i in 0..n { if self.next_back().is_none() { // SAFETY: `i` is always less than `n`. @@ -239,8 +241,10 @@ pub const trait DoubleEndedIterator: [const] Iterator { /// ``` #[inline] #[stable(feature = "iter_nth_back", since = "1.37.0")] - #[rustc_non_const_trait_method] - fn nth_back(&mut self, n: usize) -> Option { + fn nth_back(&mut self, n: usize) -> Option + where + Self::Item: [const] Destruct, + { if self.advance_back_by(n).is_err() { return None; } diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index 0748274c401fc..cc4077d0ee26f 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -306,14 +306,22 @@ pub const trait Iterator { /// ``` #[inline] #[unstable(feature = "iter_advance_by", issue = "77404")] - #[rustc_non_const_trait_method] - fn advance_by(&mut self, n: usize) -> Result<(), NonZero> { + fn advance_by(&mut self, n: usize) -> Result<(), NonZero> + where + Self::Item: [const] Destruct, + { /// Helper trait to specialize `advance_by` via `try_fold` for `Sized` iterators. - trait SpecAdvanceBy { + + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const trait SpecAdvanceBy { fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero>; } - impl SpecAdvanceBy for I { + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const impl SpecAdvanceBy for I + where + I::Item: [const] Destruct, + { default fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero> { for i in 0..n { if self.next().is_none() { @@ -325,13 +333,17 @@ pub const trait Iterator { } } - impl SpecAdvanceBy for I { + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const impl SpecAdvanceBy for I + where + I::Item: [const] Destruct, + { fn spec_advance_by(&mut self, n: usize) -> Result<(), NonZero> { let Some(n) = NonZero::new(n) else { return Ok(()); }; - let res = self.try_fold(n, |n, _| NonZero::new(n.get() - 1)); + let res = self.try_fold(n, const |n, _| NonZero::new(n.get() - 1)); match res { None => Ok(()), @@ -384,8 +396,10 @@ pub const trait Iterator { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_non_const_trait_method] - fn nth(&mut self, n: usize) -> Option { + fn nth(&mut self, n: usize) -> Option + 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 1e6704fe524a9..fd96424566bcc 100644 --- a/library/core/src/iter/traits/marker.rs +++ b/library/core/src/iter/traits/marker.rs @@ -115,4 +115,5 @@ pub unsafe trait InPlaceIterable { /// 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 + Copy {} +#[rustc_const_unstable(feature = "const_iter", issue = "92476")] +pub const unsafe trait TrustedStep: [const] Step + Copy {} diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index cd3fc889ecdd5..fcdde758fa7df 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -126,14 +126,11 @@ where // Implemented as explicit indexing rather // than zipped iterators for performance reasons. // See PR https://github.com/rust-lang/rust/pull/116846 - // FIXME(const_hack): make this a `for idx in 0..len` loop. - let mut idx = 0; - while idx < len { + for idx in 0..len { // SAFETY: idx < len, so both are in-bounds and readable if unsafe { *lhs.add(idx) != *rhs.add(idx) } { return false; } - idx += 1; } true @@ -224,11 +221,8 @@ const fn chaining_impl<'l, 'r, A: PartialOrd, B, C>( let lhs = &left[..l]; let rhs = &right[..l]; - // FIXME(const-hack): revert this to `for i in 0..l` once `impl const Iterator for Range` - let mut i: usize = 0; - while i < l { + for i in 0..l { elem_chain(&lhs[i], &rhs[i])?; - i += 1; } len_chain(&left.len(), &right.len()) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index f787b7994ba9d..6efc9e4f28a16 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -5628,11 +5628,8 @@ where // But since it can't be relied on we also have an explicit specialization for T: Copy. let len = self.len(); let src = &src[..len]; - // FIXME(const_hack): make this a `for idx in 0..self.len()` loop. - let mut idx = 0; - while idx < self.len() { - self[idx].clone_from(&src[idx]); - idx += 1; + for i in 0..len { + self[i].clone_from(&src[i]); } } } diff --git a/tests/codegen-llvm/array-cmp.rs b/tests/codegen-llvm/array-cmp.rs index 5b0a802f4097e..2eb498d08f254 100644 --- a/tests/codegen-llvm/array-cmp.rs +++ b/tests/codegen-llvm/array-cmp.rs @@ -42,6 +42,16 @@ pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> bool { // CHECK: %[[EQ00:.+]] = icmp eq i16 %[[A00]], %[[B00]] // CHECK-NEXT: br i1 %[[EQ00]], label %[[L01:.+]], label %[[EXIT_S:.+]] + // CHECK: [[L01]]: + // CHECK: %[[PA01:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 2 + // CHECK: %[[PB01:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 2 + // CHECK: %[[A01:.+]] = load i16, ptr %[[PA01]] + // CHECK: %[[B01:.+]] = load i16, ptr %[[PB01]] + // CHECK-NOT: cmp + // CHECK: %[[EQ01:.+]] = icmp eq i16 %[[A01]], %[[B01]] + // CHECK-NEXT: br i1 %[[EQ01]], label %[[L10:.+]], label %[[EXIT_U:.+]] + + // CHECK: [[L10]]: // CHECK: %[[PA10:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 4 // CHECK: %[[PB10:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 4 // CHECK: %[[A10:.+]] = load i16, ptr %[[PA10]] @@ -57,16 +67,7 @@ pub fn array_of_tuple_le(a: &[(i16, u16); 2], b: &[(i16, u16); 2]) -> bool { // CHECK: %[[B11:.+]] = load i16, ptr %[[PB11]] // CHECK-NOT: cmp // CHECK: %[[EQ11:.+]] = icmp eq i16 %[[A11]], %[[B11]] - // CHECK-NEXT: br i1 %[[EQ11]], label %[[DONE:.+]], label %[[EXIT_U:.+]] - - // CHECK: [[L01]]: - // CHECK: %[[PA01:.+]] = getelementptr{{.+}}i8, ptr %a, {{i32|i64}} 2 - // CHECK: %[[PB01:.+]] = getelementptr{{.+}}i8, ptr %b, {{i32|i64}} 2 - // CHECK: %[[A01:.+]] = load i16, ptr %[[PA01]] - // CHECK: %[[B01:.+]] = load i16, ptr %[[PB01]] - // CHECK-NOT: cmp - // CHECK: %[[EQ01:.+]] = icmp eq i16 %[[A01]], %[[B01]] - // CHECK-NEXT: br i1 %[[EQ01]], label %{{.+}}, label %[[EXIT_U]] + // CHECK-NEXT: br i1 %[[EQ11]], label %[[DONE:.+]], label %[[EXIT_U]] // CHECK: [[DONE]]: // LLVM22: %[[RET:.+]] = phi i1 [ %{{.+}}, %[[EXIT_S]] ], [ %{{.+}}, %[[EXIT_U]] ], [ true, %[[L11]] ] diff --git a/tests/ui/consts/const-for-feature-gate.rs b/tests/ui/consts/const-for-feature-gate.rs index b643e63c09690..1024beace3d89 100644 --- a/tests/ui/consts/const-for-feature-gate.rs +++ b/tests/ui/consts/const-for-feature-gate.rs @@ -3,7 +3,9 @@ const _: () = { for _ in 0..5 {} //~^ ERROR cannot use `for` + //~| ERROR `IntoIterator` is not yet stable //~| ERROR cannot use `for` + //~| ERROR `Iterator` is not yet stable }; fn main() {} diff --git a/tests/ui/consts/const-for-feature-gate.stderr b/tests/ui/consts/const-for-feature-gate.stderr index 29db5d24ac866..5876f1476341c 100644 --- a/tests/ui/consts/const-for-feature-gate.stderr +++ b/tests/ui/consts/const-for-feature-gate.stderr @@ -1,20 +1,48 @@ -error[E0015]: cannot use `for` loop on `std::ops::Range` in constants +error[E0658]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for-feature-gate.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0015]: cannot use `for` loop on `std::ops::Range` in constants +error: `IntoIterator` is not yet stable as a const trait + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | +help: add `#![feature(const_iter)]` to the crate attributes to enable + | +LL + #![feature(const_iter)] + | + +error[E0658]: cannot use `for` loop on `std::ops::Range` in constants --> $DIR/const-for-feature-gate.rs:4:14 | LL | for _ in 0..5 {} | ^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: aborting due to 2 previous errors +error: `Iterator` is not yet stable as a const trait + --> $DIR/const-for-feature-gate.rs:4:14 + | +LL | for _ in 0..5 {} + | ^^^^ + | +help: add `#![feature(const_iter)]` to the crate attributes to enable + | +LL + #![feature(const_iter)] + | + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/consts/const-for.rs b/tests/ui/consts/const-for.rs index 6f7895457c53d..5b9bcff410144 100644 --- a/tests/ui/consts/const-for.rs +++ b/tests/ui/consts/const-for.rs @@ -1,9 +1,8 @@ -#![feature(const_for)] +//@ check-pass +#![feature(const_trait_impl,const_iter,const_for)] const _: () = { for _ in 0..5 {} - //~^ ERROR cannot use `for` - //~| ERROR cannot use `for` }; fn main() {} diff --git a/tests/ui/consts/const-for.stderr b/tests/ui/consts/const-for.stderr deleted file mode 100644 index d1308a8dedc85..0000000000000 --- a/tests/ui/consts/const-for.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0015]: cannot use `for` loop on `std::ops::Range` in constants - --> $DIR/const-for.rs:4:14 - | -LL | for _ in 0..5 {} - | ^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot use `for` loop on `std::ops::Range` in constants - --> $DIR/const-for.rs:4:14 - | -LL | for _ in 0..5 {} - | ^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/control-flow/loop.rs b/tests/ui/consts/control-flow/loop.rs index b02c31c4c25b5..7da88dfd2ac89 100644 --- a/tests/ui/consts/control-flow/loop.rs +++ b/tests/ui/consts/control-flow/loop.rs @@ -1,3 +1,6 @@ +//@ check-pass +#![feature(const_iter,const_trait_impl)] + const _: () = loop { break (); }; static FOO: i32 = loop { break 4; }; @@ -51,14 +54,10 @@ const _: i32 = { let mut x = 0; for i in 0..4 { - //~^ ERROR: cannot use `for` - //~| ERROR: cannot use `for` x += i; } for i in 0..4 { - //~^ ERROR: cannot use `for` - //~| ERROR: cannot use `for` x += i; } diff --git a/tests/ui/consts/control-flow/loop.stderr b/tests/ui/consts/control-flow/loop.stderr deleted file mode 100644 index b91371f9dc218..0000000000000 --- a/tests/ui/consts/control-flow/loop.stderr +++ /dev/null @@ -1,37 +0,0 @@ -error[E0015]: cannot use `for` loop on `std::ops::Range` in constants - --> $DIR/loop.rs:53:14 - | -LL | for i in 0..4 { - | ^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot use `for` loop on `std::ops::Range` in constants - --> $DIR/loop.rs:53:14 - | -LL | for i in 0..4 { - | ^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot use `for` loop on `std::ops::Range` in constants - --> $DIR/loop.rs:59:14 - | -LL | for i in 0..4 { - | ^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot use `for` loop on `std::ops::Range` in constants - --> $DIR/loop.rs:59:14 - | -LL | for i in 0..4 { - | ^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs index 7616e391a35a9..2eda0c5863471 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.rs +++ b/tests/ui/typeck/typeck_type_placeholder_item.rs @@ -239,5 +239,6 @@ fn evens_squared(n: usize) -> _ { const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); //~^ ERROR the placeholder +//~| ERROR `Iterator` is not yet stable //~| ERROR cannot call //~| ERROR cannot call diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr index 2772d55f953a8..469c41b286a75 100644 --- a/tests/ui/typeck/typeck_type_placeholder_item.stderr +++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr @@ -678,13 +678,27 @@ LL | fn map(_: fn() -> Option<&'static T>) -> Option { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const method ` as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}>` in constants +error[E0658]: cannot call conditionally-const method ` as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}>` in constants --> $DIR/typeck_type_placeholder_item.rs:240:22 | LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | ^^^^^^^^^^^^^^^^^^^^^^ | = note: calls in constants are limited to constant functions, tuple structs and tuple variants + = note: see issue #143874 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: `Iterator` is not yet stable as a const trait + --> $DIR/typeck_type_placeholder_item.rs:240:14 + | +LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: add `#![feature(const_iter)]` to the crate attributes to enable + | +LL + #![feature(const_iter)] + | error[E0015]: cannot call non-const method `, {closure@$DIR/typeck_type_placeholder_item.rs:240:29: 240:32}> as Iterator>::map::` in constants --> $DIR/typeck_type_placeholder_item.rs:240:45 @@ -694,7 +708,7 @@ LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x); | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 83 previous errors +error: aborting due to 84 previous errors -Some errors have detailed explanations: E0015, E0046, E0121, E0282, E0403. +Some errors have detailed explanations: E0015, E0046, E0121, E0282, E0403, E0658. For more information about an error, try `rustc --explain E0015`.