about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-10-25 11:35:26 +0000
committerbors <bors@rust-lang.org>2020-10-25 11:35:26 +0000
commitf392479de6b003e72f93cb8f9955b3cf4135c2cd (patch)
tree057548a962b16b3c490cf339db151d1e0eeba81c /library
parent5171cc76c264fd46f32e140c2e460c77ca87d5e5 (diff)
parent0a26e4ba7e112b9d5ef2bd735b1486b84e66eeae (diff)
downloadrust-f392479de6b003e72f93cb8f9955b3cf4135c2cd.tar.gz
rust-f392479de6b003e72f93cb8f9955b3cf4135c2cd.zip
Auto merge of #78350 - JohnTitor:rollup-vbbm5wf, r=JohnTitor
Rollup of 8 pull requests

Successful merges:

 - #77984 (Compute proper module parent during resolution)
 - #78085 (MIR validation should check `SwitchInt` values are valid for the type)
 - #78208 (replace `#[allow_internal_unstable]` with `#[rustc_allow_const_fn_unstable]` for `const fn`s)
 - #78209 (Update `compiler_builtins` to 0.1.36)
 - #78276 (Bump backtrace-rs to enable Mach-O support on iOS.)
 - #78320 (Link to cargo's `build-std` feature instead of `xargo` in custom target docs)
 - #78322 (BTreeMap: stop mistaking node::MIN_LEN for a node level constraint)
 - #78326 (Split out statement attributes changes from #78306)

Failed merges:

r? `@ghost`
Diffstat (limited to 'library')
-rw-r--r--library/alloc/src/collections/btree/map.rs8
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs21
-rw-r--r--library/alloc/src/collections/btree/node.rs2
-rw-r--r--library/alloc/src/collections/btree/node/tests.rs56
-rw-r--r--library/alloc/src/collections/btree/remove.rs5
-rw-r--r--library/alloc/src/collections/btree/split.rs18
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/raw_vec.rs3
m---------library/backtrace0
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/num/int_macros.rs6
-rw-r--r--library/core/src/num/uint_macros.rs6
-rw-r--r--library/core/src/slice/mod.rs3
-rw-r--r--library/core/src/str/converts.rs3
-rw-r--r--library/core/src/str/mod.rs3
-rw-r--r--library/core/src/task/wake.rs3
-rw-r--r--library/proc_macro/src/bridge/client.rs15
-rw-r--r--library/proc_macro/src/bridge/scoped_cell.rs3
-rw-r--r--library/proc_macro/src/lib.rs1
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/net/ip.rs3
21 files changed, 91 insertions, 71 deletions
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 20c6ebd2292..4f9aa44b6b5 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -17,6 +17,10 @@ mod entry;
 pub use entry::{Entry, OccupiedEntry, VacantEntry};
 use Entry::*;
 
+/// Minimum number of elements in nodes that are not a root.
+/// We might temporarily have fewer elements during methods.
+pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
+
 /// A map based on a B-Tree.
 ///
 /// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
@@ -1094,13 +1098,13 @@ impl<K: Ord, V> BTreeMap<K, V> {
             // Check if right-most child is underfull.
             let mut last_edge = internal.last_edge();
             let right_child_len = last_edge.reborrow().descend().len();
-            if right_child_len < node::MIN_LEN {
+            if right_child_len < MIN_LEN {
                 // We need to steal.
                 let mut last_kv = match last_edge.left_kv() {
                     Ok(left) => left,
                     Err(_) => unreachable!(),
                 };
-                last_kv.bulk_steal_left(node::MIN_LEN - right_child_len);
+                last_kv.bulk_steal_left(MIN_LEN - right_child_len);
                 last_edge = last_kv.right_edge();
             }
 
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index b51b95a635c..adb94972f5b 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -50,10 +50,15 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
     {
         if let Some(root) = &self.root {
             let root_node = root.node_as_ref();
+
             assert!(root_node.ascend().is_err());
             root_node.assert_back_pointers();
-            root_node.assert_ascending();
-            assert_eq!(self.length, root_node.assert_and_add_lengths());
+
+            let counted = root_node.assert_ascending();
+            assert_eq!(self.length, counted);
+            assert_eq!(self.length, root_node.calc_length());
+
+            root_node.assert_min_len(if root_node.height() > 0 { 1 } else { 0 });
         } else {
             assert_eq!(self.length, 0);
         }
@@ -76,6 +81,18 @@ impl<'a, K: 'a, V: 'a> BTreeMap<K, V> {
     }
 }
 
+impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> {
+    pub fn assert_min_len(self, min_len: usize) {
+        assert!(self.len() >= min_len, "{} < {}", self.len(), min_len);
+        if let node::ForceResult::Internal(node) = self.force() {
+            for idx in 0..=node.len() {
+                let edge = unsafe { Handle::new_edge(node, idx) };
+                edge.descend().assert_min_len(MIN_LEN);
+            }
+        }
+    }
+}
+
 // Test our value of MIN_INSERTS_HEIGHT_2. It may change according to the
 // implementation of insertion, but it's best to be aware of when it does.
 #[test]
diff --git a/library/alloc/src/collections/btree/node.rs b/library/alloc/src/collections/btree/node.rs
index 886d8abd030..f5aff9bf494 100644
--- a/library/alloc/src/collections/btree/node.rs
+++ b/library/alloc/src/collections/btree/node.rs
@@ -38,8 +38,8 @@ use crate::alloc::{AllocRef, Global, Layout};
 use crate::boxed::Box;
 
 const B: usize = 6;
-pub const MIN_LEN: usize = B - 1;
 pub const CAPACITY: usize = 2 * B - 1;
+pub const MIN_LEN_AFTER_SPLIT: usize = B - 1;
 const KV_IDX_CENTER: usize = B - 1;
 const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1;
 const EDGE_IDX_RIGHT_OF_CENTER: usize = B;
diff --git a/library/alloc/src/collections/btree/node/tests.rs b/library/alloc/src/collections/btree/node/tests.rs
index e56fc2aa51e..d6527057c5d 100644
--- a/library/alloc/src/collections/btree/node/tests.rs
+++ b/library/alloc/src/collections/btree/node/tests.rs
@@ -5,25 +5,26 @@ use crate::string::String;
 use core::cmp::Ordering::*;
 
 impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal> {
+    /// Asserts that the back pointer in each reachable node points to its parent.
     pub fn assert_back_pointers(self) {
-        match self.force() {
-            ForceResult::Leaf(_) => {}
-            ForceResult::Internal(node) => {
-                for idx in 0..=node.len() {
-                    let edge = unsafe { Handle::new_edge(node, idx) };
-                    let child = edge.descend();
-                    assert!(child.ascend().ok() == Some(edge));
-                    child.assert_back_pointers();
-                }
+        if let ForceResult::Internal(node) = self.force() {
+            for idx in 0..=node.len() {
+                let edge = unsafe { Handle::new_edge(node, idx) };
+                let child = edge.descend();
+                assert!(child.ascend().ok() == Some(edge));
+                child.assert_back_pointers();
             }
         }
     }
 
-    pub fn assert_ascending(self)
+    /// Asserts that the keys are in strictly ascending order.
+    /// Returns how many keys it encountered.
+    pub fn assert_ascending(self) -> usize
     where
         K: Copy + Debug + Ord,
     {
         struct SeriesChecker<T> {
+            num_seen: usize,
             previous: Option<T>,
         }
         impl<T: Copy + Debug + Ord> SeriesChecker<T> {
@@ -32,10 +33,11 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
                     assert!(previous < next, "{:?} >= {:?}", previous, next);
                 }
                 self.previous = Some(next);
+                self.num_seen += 1;
             }
         }
 
-        let mut checker = SeriesChecker { previous: None };
+        let mut checker = SeriesChecker { num_seen: 0, previous: None };
         self.visit_nodes_in_order(|pos| match pos {
             navigate::Position::Leaf(node) => {
                 for idx in 0..node.len() {
@@ -49,33 +51,7 @@ impl<'a, K: 'a, V: 'a> NodeRef<marker::Immut<'a>, K, V, marker::LeafOrInternal>
             }
             navigate::Position::Internal(_) => {}
         });
-    }
-
-    pub fn assert_and_add_lengths(self) -> usize {
-        let mut internal_length = 0;
-        let mut internal_kv_count = 0;
-        let mut leaf_length = 0;
-        self.visit_nodes_in_order(|pos| match pos {
-            navigate::Position::Leaf(node) => {
-                let is_root = self.height() == 0;
-                let min_len = if is_root { 0 } else { MIN_LEN };
-                assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
-                leaf_length += node.len();
-            }
-            navigate::Position::Internal(node) => {
-                let is_root = self.height() == node.height();
-                let min_len = if is_root { 1 } else { MIN_LEN };
-                assert!(node.len() >= min_len, "{} < {}", node.len(), min_len);
-                internal_length += node.len();
-            }
-            navigate::Position::InternalKV(_) => {
-                internal_kv_count += 1;
-            }
-        });
-        assert_eq!(internal_length, internal_kv_count);
-        let total = internal_length + leaf_length;
-        assert_eq!(self.calc_length(), total);
-        total
+        checker.num_seen
     }
 
     pub fn dump_keys(self) -> String
@@ -124,8 +100,8 @@ fn test_splitpoint() {
                 right_len += 1;
             }
         }
-        assert!(left_len >= MIN_LEN);
-        assert!(right_len >= MIN_LEN);
+        assert!(left_len >= MIN_LEN_AFTER_SPLIT);
+        assert!(right_len >= MIN_LEN_AFTER_SPLIT);
         assert!(left_len + right_len == CAPACITY);
     }
 }
diff --git a/library/alloc/src/collections/btree/remove.rs b/library/alloc/src/collections/btree/remove.rs
index 9733b7d6084..99655d3e2bf 100644
--- a/library/alloc/src/collections/btree/remove.rs
+++ b/library/alloc/src/collections/btree/remove.rs
@@ -1,4 +1,5 @@
-use super::node::{self, marker, ForceResult, Handle, NodeRef};
+use super::map::MIN_LEN;
+use super::node::{marker, ForceResult, Handle, NodeRef};
 use super::unwrap_unchecked;
 use core::mem;
 use core::ptr;
@@ -40,7 +41,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInter
         // Handle underflow
         let mut cur_node = unsafe { ptr::read(&pos).into_node().forget_type() };
         let mut at_leaf = true;
-        while cur_node.len() < node::MIN_LEN {
+        while cur_node.len() < MIN_LEN {
             match handle_underfull_node(cur_node) {
                 UnderflowResult::AtRoot => break,
                 UnderflowResult::Merged(edge, merged_with_left, offset) => {
diff --git a/library/alloc/src/collections/btree/split.rs b/library/alloc/src/collections/btree/split.rs
index 0e6e213f6e8..5f00a5a25ab 100644
--- a/library/alloc/src/collections/btree/split.rs
+++ b/library/alloc/src/collections/btree/split.rs
@@ -1,5 +1,6 @@
-use super::node::{self, ForceResult::*, Root};
-use super::search::{self, SearchResult::*};
+use super::map::MIN_LEN;
+use super::node::{ForceResult::*, Root};
+use super::search::{search_node, SearchResult::*};
 use core::borrow::Borrow;
 
 impl<K, V> Root<K, V> {
@@ -20,7 +21,7 @@ impl<K, V> Root<K, V> {
             let mut right_node = right_root.node_as_mut();
 
             loop {
-                let mut split_edge = match search::search_node(left_node, key) {
+                let mut split_edge = match search_node(left_node, key) {
                     // key is going to the right tree
                     Found(handle) => handle.left_edge(),
                     GoDown(handle) => handle,
@@ -65,9 +66,9 @@ impl<K, V> Root<K, V> {
                     cur_node = last_kv.merge().descend();
                 } else {
                     let right_len = last_kv.reborrow().right_edge().descend().len();
-                    // `MINLEN + 1` to avoid readjust if merge happens on the next level.
-                    if right_len < node::MIN_LEN + 1 {
-                        last_kv.bulk_steal_left(node::MIN_LEN + 1 - right_len);
+                    // `MIN_LEN + 1` to avoid readjust if merge happens on the next level.
+                    if right_len < MIN_LEN + 1 {
+                        last_kv.bulk_steal_left(MIN_LEN + 1 - right_len);
                     }
                     cur_node = last_kv.right_edge().descend();
                 }
@@ -91,8 +92,9 @@ impl<K, V> Root<K, V> {
                     cur_node = first_kv.merge().descend();
                 } else {
                     let left_len = first_kv.reborrow().left_edge().descend().len();
-                    if left_len < node::MIN_LEN + 1 {
-                        first_kv.bulk_steal_right(node::MIN_LEN + 1 - left_len);
+                    // `MIN_LEN + 1` to avoid readjust if merge happens on the next level.
+                    if left_len < MIN_LEN + 1 {
+                        first_kv.bulk_steal_right(MIN_LEN + 1 - left_len);
                     }
                     cur_node = first_kv.left_edge().descend();
                 }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index c039be8f67c..0fe15958076 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -72,6 +72,7 @@
 #![allow(explicit_outlives_requirements)]
 #![allow(incomplete_features)]
 #![deny(unsafe_op_in_unsafe_fn)]
+#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
 #![cfg_attr(not(test), feature(generator_trait))]
 #![cfg_attr(test, feature(test))]
 #![cfg_attr(test, feature(new_uninit))]
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index 7c834f034c1..657b568e7f6 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -150,7 +150,8 @@ impl<T> RawVec<T, Global> {
 impl<T, A: AllocRef> RawVec<T, A> {
     /// Like `new`, but parameterized over the choice of allocator for
     /// the returned `RawVec`.
-    #[allow_internal_unstable(const_fn)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
     pub const fn new_in(alloc: A) -> Self {
         // `cap: 0` means "unallocated". zero-sized types are ignored.
         Self { ptr: Unique::dangling(), cap: 0, alloc }
diff --git a/library/backtrace b/library/backtrace
-Subproject a6dd47bd588c882e735675a1379d2b61719fa38
+Subproject 8b8ea53b56f519dd7780defdd4254daaec89258
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index af4b7199397..6cb240d1730 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -63,6 +63,7 @@
 #![warn(missing_debug_implementations)]
 #![allow(explicit_outlives_requirements)]
 #![allow(incomplete_features)]
+#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
 #![feature(allow_internal_unstable)]
 #![feature(arbitrary_self_types)]
 #![feature(asm)]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 33fa26675f6..295a876773c 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2045,7 +2045,8 @@ assert_eq!(
             #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute them to arrays of bytes
-            #[allow_internal_unstable(const_fn_transmute)]
+            #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+            #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
             #[inline]
             pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 // SAFETY: integers are plain old datatypes so we can always transmute them to
@@ -2193,7 +2194,8 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
             #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute to them
-            #[allow_internal_unstable(const_fn_transmute)]
+            #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+            #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
             #[inline]
             pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 // SAFETY: integers are plain old datatypes so we can always transmute to them
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 0de1cc6b165..bdea0ea3b08 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1803,7 +1803,8 @@ assert_eq!(
             #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute them to arrays of bytes
-            #[allow_internal_unstable(const_fn_transmute)]
+            #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+            #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
             #[inline]
             pub const fn to_ne_bytes(self) -> [u8; mem::size_of::<Self>()] {
                 // SAFETY: integers are plain old datatypes so we can always transmute them to
@@ -1951,7 +1952,8 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT),
             #[rustc_const_stable(feature = "const_int_conversion", since = "1.44.0")]
             // SAFETY: const sound because integers are plain old datatypes so we can always
             // transmute to them
-            #[allow_internal_unstable(const_fn_transmute)]
+            #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+            #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
             #[inline]
             pub const fn from_ne_bytes(bytes: [u8; mem::size_of::<Self>()]) -> Self {
                 // SAFETY: integers are plain old datatypes so we can always transmute to them
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 376ad321f64..b6fd0c4986b 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -88,7 +88,8 @@ impl<T> [T] {
     #[rustc_const_stable(feature = "const_slice_len", since = "1.32.0")]
     #[inline]
     // SAFETY: const sound because we transmute out the length field as a usize (which it must be)
-    #[allow_internal_unstable(const_fn_union)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_union))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_union))]
     pub const fn len(&self) -> usize {
         // SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
         // Only `std` can make this guarantee.
diff --git a/library/core/src/str/converts.rs b/library/core/src/str/converts.rs
index de2a93f7350..952d0598a7c 100644
--- a/library/core/src/str/converts.rs
+++ b/library/core/src/str/converts.rs
@@ -157,7 +157,8 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")]
-#[allow_internal_unstable(const_fn_transmute)]
+#[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+#[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
 pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
     // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
     // Also relies on `&str` and `&[u8]` having the same layout.
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 3e18a4e7062..ee9c09fe186 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -219,7 +219,8 @@ impl str {
     #[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
     #[inline(always)]
     #[allow(unused_attributes)]
-    #[allow_internal_unstable(const_fn_transmute)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
     pub const fn as_bytes(&self) -> &[u8] {
         // SAFETY: const sound because we transmute two types with the same layout
         unsafe { mem::transmute(self) }
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 8cca9dc9042..d3c0d9b7841 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -130,7 +130,8 @@ impl RawWakerVTable {
     #[rustc_promotable]
     #[stable(feature = "futures_api", since = "1.36.0")]
     #[rustc_const_stable(feature = "futures_api", since = "1.36.0")]
-    #[allow_internal_unstable(const_fn_fn_ptr_basics)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_fn_ptr_basics))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_fn_ptr_basics))]
     pub const fn new(
         clone: unsafe fn(*const ()) -> RawWaker,
         wake: unsafe fn(*const ()),
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index ba3d4c075e1..dfe5df965cf 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -401,7 +401,8 @@ fn run_client<A: for<'a, 's> DecodeMut<'a, 's, ()>, R: Encode<()>>(
 }
 
 impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
-    #[allow_internal_unstable(const_fn)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
     pub const fn expand1(f: fn(crate::TokenStream) -> crate::TokenStream) -> Self {
         extern "C" fn run(
             bridge: Bridge<'_>,
@@ -414,7 +415,8 @@ impl Client<fn(crate::TokenStream) -> crate::TokenStream> {
 }
 
 impl Client<fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream> {
-    #[allow_internal_unstable(const_fn)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
     pub const fn expand2(
         f: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
     ) -> Self {
@@ -459,7 +461,8 @@ impl ProcMacro {
         }
     }
 
-    #[allow_internal_unstable(const_fn)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
     pub const fn custom_derive(
         trait_name: &'static str,
         attributes: &'static [&'static str],
@@ -468,7 +471,8 @@ impl ProcMacro {
         ProcMacro::CustomDerive { trait_name, attributes, client: Client::expand1(expand) }
     }
 
-    #[allow_internal_unstable(const_fn)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
     pub const fn attr(
         name: &'static str,
         expand: fn(crate::TokenStream, crate::TokenStream) -> crate::TokenStream,
@@ -476,7 +480,8 @@ impl ProcMacro {
         ProcMacro::Attr { name, client: Client::expand2(expand) }
     }
 
-    #[allow_internal_unstable(const_fn)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
     pub const fn bang(
         name: &'static str,
         expand: fn(crate::TokenStream) -> crate::TokenStream,
diff --git a/library/proc_macro/src/bridge/scoped_cell.rs b/library/proc_macro/src/bridge/scoped_cell.rs
index daa577f74ba..e7c32b10384 100644
--- a/library/proc_macro/src/bridge/scoped_cell.rs
+++ b/library/proc_macro/src/bridge/scoped_cell.rs
@@ -35,7 +35,8 @@ impl<'a, 'b, T: LambdaL> DerefMut for RefMutL<'a, 'b, T> {
 pub struct ScopedCell<T: LambdaL>(Cell<<T as ApplyL<'static>>::Out>);
 
 impl<T: LambdaL> ScopedCell<T> {
-    #[allow_internal_unstable(const_fn)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn))]
     pub const fn new(value: <T as ApplyL<'static>>::Out) -> Self {
         ScopedCell(Cell::new(value))
     }
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index 139b3591206..5a4b69cf6fc 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -18,6 +18,7 @@
     test(no_crate_inject, attr(deny(warnings))),
     test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
 )]
+#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
 #![feature(nll)]
 #![feature(staged_api)]
 #![feature(const_fn)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 3da0ebdd498..96a7755c688 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -206,6 +206,7 @@
 #![needs_panic_runtime]
 // std may use features in a platform-specific way
 #![allow(unused_features)]
+#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
 #![cfg_attr(test, feature(print_internals, set_stdio, update_panic_count))]
 #![cfg_attr(
     all(target_vendor = "fortanix", target_env = "sgx"),
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 8089d7a8ba6..bb3ece4c273 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -1043,7 +1043,8 @@ impl Ipv6Addr {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
-    #[allow_internal_unstable(const_fn_transmute)]
+    #[cfg_attr(not(bootstrap), rustc_allow_const_fn_unstable(const_fn_transmute))]
+    #[cfg_attr(bootstrap, allow_internal_unstable(const_fn_transmute))]
     pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
         let addr16 = [
             a.to_be(),