about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast.rs14
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0723.md16
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_mir/src/transform/check_consts/ops.rs11
-rw-r--r--compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs9
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/slice/iter.rs29
-rw-r--r--library/core/src/slice/mod.rs3
-rw-r--r--src/test/codegen/slice-windows-no-bounds-check.rs35
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs7
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr18
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53096.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs2
-rw-r--r--src/test/ui/type-alias-impl-trait/structural-match.rs2
16 files changed, 106 insertions, 49 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 492d5788fc0..8d9d4123c79 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -27,6 +27,7 @@ use crate::token::{self, CommentKind, DelimToken};
 use crate::tokenstream::{DelimSpan, TokenStream, TokenTree};
 
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_macros::HashStable_Generic;
@@ -1864,7 +1865,7 @@ pub enum AssocTyConstraintKind {
     Bound { bounds: GenericBounds },
 }
 
-#[derive(Clone, Encodable, Decodable, Debug)]
+#[derive(Encodable, Decodable, Debug)]
 pub struct Ty {
     pub id: NodeId,
     pub kind: TyKind,
@@ -1872,6 +1873,17 @@ pub struct Ty {
     pub tokens: Option<TokenStream>,
 }
 
+impl Clone for Ty {
+    fn clone(&self) -> Self {
+        ensure_sufficient_stack(|| Self {
+            id: self.id,
+            kind: self.kind.clone(),
+            span: self.span,
+            tokens: self.tokens.clone(),
+        })
+    }
+}
+
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct BareFnTy {
     pub unsafety: Unsafe,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0723.md b/compiler/rustc_error_codes/src/error_codes/E0723.md
index 95d47ab21cb..bc224421915 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0723.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0723.md
@@ -3,12 +3,8 @@ An unstable feature in `const` contexts was used.
 Erroneous code example:
 
 ```compile_fail,E0723
-trait T {}
-
-impl T for () {}
-
-const fn foo() -> impl T { // error: `impl Trait` in const fn is unstable
-    ()
+const fn foo<T: Copy>(_: T) { // error!
+   // ...
 }
 ```
 
@@ -18,11 +14,7 @@ feature flag:
 ```
 #![feature(const_fn)]
 
-trait T {}
-
-impl T for () {}
-
-const fn foo() -> impl T {
-    ()
+const fn foo<T: Copy>(_: T) { // ok!
+   // ...
 }
 ```
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index cd018ae1204..1982d098542 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -596,6 +596,9 @@ declare_features! (
     /// Allows rustc to inject a default alloc_error_handler
     (active, default_alloc_error_handler, "1.48.0", Some(66741), None),
 
+    /// Allows argument and return position `impl Trait` in a `const fn`.
+    (active, const_impl_trait, "1.48.0", Some(77463), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_mir/src/transform/check_consts/ops.rs b/compiler/rustc_mir/src/transform/check_consts/ops.rs
index 9a1b77e994d..63b20c7c027 100644
--- a/compiler/rustc_mir/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_mir/src/transform/check_consts/ops.rs
@@ -558,12 +558,17 @@ pub mod ty {
     #[derive(Debug)]
     pub struct ImplTrait;
     impl NonConstOp for ImplTrait {
-        fn status_in_item(&self, ccx: &ConstCx<'_, '_>) -> Status {
-            mcf_status_in_item(ccx)
+        fn status_in_item(&self, _: &ConstCx<'_, '_>) -> Status {
+            Status::Unstable(sym::const_impl_trait)
         }
 
         fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> DiagnosticBuilder<'tcx> {
-            mcf_build_error(ccx, span, "`impl Trait` in const fn is unstable")
+            feature_err(
+                &ccx.tcx.sess.parse_sess,
+                sym::const_impl_trait,
+                span,
+                &format!("`impl Trait` is not allowed in {}s", ccx.const_kind()),
+            )
         }
     }
 
diff --git a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs
index a6bfa0c7409..87906e83ed5 100644
--- a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs
+++ b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs
@@ -1,6 +1,7 @@
 //! A pass that eliminates branches on uninhabited enum variants.
 
 use crate::transform::MirPass;
+use rustc_data_structures::stable_set::FxHashSet;
 use rustc_middle::mir::{
     BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind,
 };
@@ -52,9 +53,13 @@ fn variant_discriminants<'tcx>(
     layout: &TyAndLayout<'tcx>,
     ty: Ty<'tcx>,
     tcx: TyCtxt<'tcx>,
-) -> Vec<u128> {
+) -> FxHashSet<u128> {
     match &layout.variants {
-        Variants::Single { index } => vec![index.as_u32() as u128],
+        Variants::Single { index } => {
+            let mut res = FxHashSet::default();
+            res.insert(index.as_u32() as u128);
+            res
+        }
         Variants::Multiple { variants, .. } => variants
             .iter_enumerated()
             .filter_map(|(idx, layout)| {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 6309b00f5f5..a2184c00a28 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -359,6 +359,7 @@ symbols! {
         const_fn_union,
         const_generics,
         const_if_match,
+        const_impl_trait,
         const_in_array_repeat_expressions,
         const_indexing,
         const_let,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 49cec162762..3aa68aa1d8d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -83,6 +83,7 @@
 #![feature(const_fn)]
 #![feature(const_fn_union)]
 #![feature(const_assume)]
+#![cfg_attr(not(bootstrap), feature(const_impl_trait))]
 #![cfg_attr(not(bootstrap), feature(const_fn_floating_point_arithmetic))]
 #![cfg_attr(not(bootstrap), feature(const_fn_fn_ptr_basics))]
 #![feature(const_generics)]
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 793cbf99495..24f955a70b6 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -10,6 +10,7 @@ use crate::intrinsics::{assume, exact_div, unchecked_sub};
 use crate::iter::{FusedIterator, TrustedLen, TrustedRandomAccess};
 use crate::marker::{PhantomData, Send, Sized, Sync};
 use crate::mem;
+use crate::num::NonZeroUsize;
 use crate::ptr::NonNull;
 
 use super::{from_raw_parts, from_raw_parts_mut};
@@ -1187,12 +1188,12 @@ forward_iterator! { RSplitNMut: T, &'a mut [T] }
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Windows<'a, T: 'a> {
     v: &'a [T],
-    size: usize,
+    size: NonZeroUsize,
 }
 
 impl<'a, T: 'a> Windows<'a, T> {
     #[inline]
-    pub(super) fn new(slice: &'a [T], size: usize) -> Self {
+    pub(super) fn new(slice: &'a [T], size: NonZeroUsize) -> Self {
         Self { v: slice, size }
     }
 }
@@ -1211,10 +1212,10 @@ impl<'a, T> Iterator for Windows<'a, T> {
 
     #[inline]
     fn next(&mut self) -> Option<&'a [T]> {
-        if self.size > self.v.len() {
+        if self.size.get() > self.v.len() {
             None
         } else {
-            let ret = Some(&self.v[..self.size]);
+            let ret = Some(&self.v[..self.size.get()]);
             self.v = &self.v[1..];
             ret
         }
@@ -1222,10 +1223,10 @@ impl<'a, T> Iterator for Windows<'a, T> {
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        if self.size > self.v.len() {
+        if self.size.get() > self.v.len() {
             (0, Some(0))
         } else {
-            let size = self.v.len() - self.size + 1;
+            let size = self.v.len() - self.size.get() + 1;
             (size, Some(size))
         }
     }
@@ -1237,7 +1238,7 @@ impl<'a, T> Iterator for Windows<'a, T> {
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<Self::Item> {
-        let (end, overflow) = self.size.overflowing_add(n);
+        let (end, overflow) = self.size.get().overflowing_add(n);
         if end > self.v.len() || overflow {
             self.v = &[];
             None
@@ -1250,10 +1251,10 @@ impl<'a, T> Iterator for Windows<'a, T> {
 
     #[inline]
     fn last(self) -> Option<Self::Item> {
-        if self.size > self.v.len() {
+        if self.size.get() > self.v.len() {
             None
         } else {
-            let start = self.v.len() - self.size;
+            let start = self.v.len() - self.size.get();
             Some(&self.v[start..])
         }
     }
@@ -1264,7 +1265,7 @@ impl<'a, T> Iterator for Windows<'a, T> {
         // which means that `i` cannot overflow an `isize`, and the
         // slice created by `from_raw_parts` is a subslice of `self.v`
         // thus is guaranteed to be valid for the lifetime `'a` of `self.v`.
-        unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size) }
+        unsafe { from_raw_parts(self.v.as_ptr().add(idx), self.size.get()) }
     }
 }
 
@@ -1272,10 +1273,10 @@ impl<'a, T> Iterator for Windows<'a, T> {
 impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<&'a [T]> {
-        if self.size > self.v.len() {
+        if self.size.get() > self.v.len() {
             None
         } else {
-            let ret = Some(&self.v[self.v.len() - self.size..]);
+            let ret = Some(&self.v[self.v.len() - self.size.get()..]);
             self.v = &self.v[..self.v.len() - 1];
             ret
         }
@@ -1284,11 +1285,11 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> {
     #[inline]
     fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
         let (end, overflow) = self.v.len().overflowing_sub(n);
-        if end < self.size || overflow {
+        if end < self.size.get() || overflow {
             self.v = &[];
             None
         } else {
-            let ret = &self.v[end - self.size..end];
+            let ret = &self.v[end - self.size.get()..end];
             self.v = &self.v[..end - 1];
             Some(ret)
         }
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 9373c6feccd..73d085c3fb2 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -11,6 +11,7 @@
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::marker::Copy;
 use crate::mem;
+use crate::num::NonZeroUsize;
 use crate::ops::{FnMut, Range, RangeBounds};
 use crate::option::Option;
 use crate::option::Option::{None, Some};
@@ -751,7 +752,7 @@ impl<T> [T] {
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn windows(&self, size: usize) -> Windows<'_, T> {
-        assert_ne!(size, 0);
+        let size = NonZeroUsize::new(size).expect("size is zero");
         Windows::new(self, size)
     }
 
diff --git a/src/test/codegen/slice-windows-no-bounds-check.rs b/src/test/codegen/slice-windows-no-bounds-check.rs
new file mode 100644
index 00000000000..4f5f4425c27
--- /dev/null
+++ b/src/test/codegen/slice-windows-no-bounds-check.rs
@@ -0,0 +1,35 @@
+#![crate_type = "lib"]
+
+// compile-flags: -O
+
+use std::slice::Windows;
+
+// CHECK-LABEL: @naive_string_search
+#[no_mangle]
+pub fn naive_string_search(haystack: &str, needle: &str) -> Option<usize> {
+    if needle.is_empty() {
+        return Some(0);
+    }
+    // CHECK-NOT: panic
+    // CHECK-NOT: fail
+    haystack
+        .as_bytes()
+        .windows(needle.len())
+        .position(|sub| sub == needle.as_bytes())
+}
+
+// CHECK-LABEL: @next
+#[no_mangle]
+pub fn next<'a>(w: &mut Windows<'a, u32>) -> Option<&'a [u32]> {
+    // CHECK-NOT: panic
+    // CHECK-NOT: fail
+    w.next()
+}
+
+// CHECK-LABEL: @next_back
+#[no_mangle]
+pub fn next_back<'a>(w: &mut Windows<'a, u32>) -> Option<&'a [u32]> {
+    // CHECK-NOT: panic
+    // CHECK-NOT: fail
+    w.next_back()
+}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs
index 9cc9b69ac0b..e062c9f0aa3 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs
@@ -1,9 +1,10 @@
+// gate-test-const_impl_trait
+
 struct AlanTuring<T>(T);
-const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> {
-    //~^ ERROR `impl Trait` in const fn is unstable
+const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> { //~ `impl Trait`
     AlanTuring(0)
 }
 
-const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable
+const fn no_rpit() -> impl std::fmt::Debug {} //~ `impl Trait`
 
 fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr
index a62a340332d..01c797cd96b 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr
@@ -1,21 +1,21 @@
-error[E0723]: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn_impl_trait.rs:2:24
+error[E0658]: `impl Trait` is not allowed in constant functions
+  --> $DIR/min_const_fn_impl_trait.rs:4:24
    |
 LL | const fn no_rpit2() -> AlanTuring<impl std::fmt::Debug> {
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn)]` to the crate attributes to enable
+   = note: see issue #77463 <https://github.com/rust-lang/rust/issues/77463> for more information
+   = help: add `#![feature(const_impl_trait)]` to the crate attributes to enable
 
-error[E0723]: `impl Trait` in const fn is unstable
-  --> $DIR/min_const_fn_impl_trait.rs:7:23
+error[E0658]: `impl Trait` is not allowed in constant functions
+  --> $DIR/min_const_fn_impl_trait.rs:8:23
    |
 LL | const fn no_rpit() -> impl std::fmt::Debug {}
    |                       ^^^^^^^^^^^^^^^^^^^^
    |
-   = note: see issue #57563 <https://github.com/rust-lang/rust/issues/57563> for more information
-   = help: add `#![feature(const_fn)]` to the crate attributes to enable
+   = note: see issue #77463 <https://github.com/rust-lang/rust/issues/77463> for more information
+   = help: add `#![feature(const_impl_trait)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0723`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/type-alias-impl-trait/issue-53096.rs b/src/test/ui/type-alias-impl-trait/issue-53096.rs
index bdf426bbd37..6e1973bd18a 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53096.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-53096.rs
@@ -1,5 +1,5 @@
 // check-pass
-#![feature(const_fn, const_fn_fn_ptr_basics)]
+#![feature(const_impl_trait, const_fn_fn_ptr_basics)]
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl Fn() -> usize;
diff --git a/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
index e7f93732430..4582d5386f0 100644
--- a/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
+++ b/src/test/ui/type-alias-impl-trait/issue-53678-generator-and-const-fn.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(const_fn, generators, generator_trait, type_alias_impl_trait)]
+#![feature(const_impl_trait, generators, generator_trait, type_alias_impl_trait)]
 
 use std::ops::Generator;
 
diff --git a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
index d50835608fa..58f0f5b2f65 100644
--- a/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
+++ b/src/test/ui/type-alias-impl-trait/structural-match-no-leak.rs
@@ -1,4 +1,4 @@
-#![feature(const_fn, type_alias_impl_trait)]
+#![feature(const_impl_trait, type_alias_impl_trait)]
 
 type Bar = impl Send;
 
diff --git a/src/test/ui/type-alias-impl-trait/structural-match.rs b/src/test/ui/type-alias-impl-trait/structural-match.rs
index a3ff4ad1d47..74ffa608426 100644
--- a/src/test/ui/type-alias-impl-trait/structural-match.rs
+++ b/src/test/ui/type-alias-impl-trait/structural-match.rs
@@ -1,4 +1,4 @@
-#![feature(const_fn, type_alias_impl_trait)]
+#![feature(const_impl_trait, type_alias_impl_trait)]
 
 type Foo = impl Send;