about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-09-16 17:02:17 +0000
committerbors <bors@rust-lang.org>2017-09-16 17:02:17 +0000
commitae8efdc87d5f4e22e05e1b60a72272cee87fa74c (patch)
treefc7932f915f347bd68db4143b2e097e620faa538 /src
parentb965d55a3214b78ec9ffdd3017cb6aaa62c28059 (diff)
parent332c38cd70e372f56356e02b18b88919fcb58a66 (diff)
downloadrust-ae8efdc87d5f4e22e05e1b60a72272cee87fa74c.tar.gz
rust-ae8efdc87d5f4e22e05e1b60a72272cee87fa74c.zip
Auto merge of #43017 - durka:stabilize-const-invocation, r=eddyb
Individualize feature gates for const fn invocation

This PR changes the meaning of `#![feature(const_fn)]` so it is only required to declare a const fn but not to call one. Based on discussion at #24111. I was hoping we could have an FCP here in order to move that conversation forward.

This sets the stage for future stabilization of the constness of several functions in the standard library (listed below), so could someone please tag the lang team for review.

- `std::cell`
    - `Cell::new`
    - `RefCell::new`
    - `UnsafeCell::new`
- `std::mem`
    - `size_of`
    - `align_of`
- `std::ptr`
    - `null`
    - `null_mut`
- `std::sync`
    - `atomic`
        - `Atomic{Bool,Ptr,Isize,Usize}::new`
    - `once`
        - `Once::new`
- primitives
    - `{integer}::min_value`
    - `{integer}::max_value`

Some other functions are const but they are also unstable or hidden, e.g. `Unique::new` so they don't have to be considered at this time.

After this stabilization, the following `*_INIT` constants in the standard library can be deprecated. I wasn't sure whether to include those deprecations in the current PR.

- `std::sync`
    - `atomic`
        - `ATOMIC_{BOOL,ISIZE,USIZE}_INIT`
    - `once`
        - `ONCE_INIT`
Diffstat (limited to 'src')
-rw-r--r--src/Cargo.lock6
-rw-r--r--src/libcore/cell.rs3
-rw-r--r--src/libcore/lib.rs18
-rw-r--r--src/libcore/mem.rs2
-rw-r--r--src/libcore/nonzero.rs4
-rw-r--r--src/libcore/num/mod.rs4
-rw-r--r--src/libcore/ptr.rs6
-rw-r--r--src/libcore/sync/atomic.rs15
-rw-r--r--src/libcore/tests/lib.rs5
-rw-r--r--src/librustc/ich/impls_syntax.rs8
-rw-r--r--src/librustc/lib.rs4
-rw-r--r--src/librustc/middle/stability.rs1
-rw-r--r--src/librustc_apfloat/lib.rs5
-rw-r--r--src/librustc_const_eval/lib.rs4
-rw-r--r--src/librustc_const_math/lib.rs5
-rw-r--r--src/librustc_mir/diagnostics.rs4
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs60
-rw-r--r--src/librustc_trans/lib.rs5
-rw-r--r--src/librustc_trans_utils/lib.rs3
-rw-r--r--src/libstd/lib.rs12
-rw-r--r--src/libstd/sync/once.rs1
-rw-r--r--src/libsyntax/attr.rs79
-rw-r--r--src/libsyntax/diagnostic_list.rs3
-rw-r--r--src/libsyntax/feature_gate.rs6
-rw-r--r--src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs3
-rw-r--r--src/test/compile-fail/const-call.rs2
-rw-r--r--src/test/compile-fail/const-fn-feature-flags.rs24
-rw-r--r--src/test/compile-fail/dropck_trait_cycle_checked.rs2
-rw-r--r--src/test/compile-fail/feature-gate-rustc_const_unstable.rs (renamed from src/test/run-pass/const-fn-cross-crate.rs)17
-rw-r--r--src/test/compile-fail/functional-struct-update-respects-privacy.rs2
-rw-r--r--src/test/compile-fail/issue-17718-const-borrow.rs2
-rw-r--r--src/test/compile-fail/issue-43733-2.rs2
-rw-r--r--src/test/compile-fail/issue-7364.rs5
-rw-r--r--src/test/compile-fail/stability-attribute-sanity.rs7
-rw-r--r--src/test/debuginfo/constant-debug-locs.rs2
-rw-r--r--src/test/run-pass-valgrind/cast-enum-with-dtor.rs2
-rw-r--r--src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs2
-rw-r--r--src/test/run-pass/auxiliary/const_fn_lib.rs2
-rw-r--r--src/test/run-pass/auxiliary/issue-17718-aux.rs2
-rw-r--r--src/test/run-pass/auxiliary/thread-local-extern-static.rs1
-rw-r--r--src/test/run-pass/box-of-array-of-drop-1.rs2
-rw-r--r--src/test/run-pass/box-of-array-of-drop-2.rs2
-rw-r--r--src/test/run-pass/const-fn-feature-flags.rs25
-rw-r--r--src/test/run-pass/const-fn-stability-calls.rs (renamed from src/test/compile-fail/const-fn-stability-calls.rs)8
-rw-r--r--src/test/run-pass/const-size_of-align_of.rs2
-rw-r--r--src/test/run-pass/issue-17718-static-unsafe-interior.rs3
-rw-r--r--src/test/run-pass/issue-17718.rs2
-rw-r--r--src/test/run-pass/issue-21486.rs2
-rw-r--r--src/test/run-pass/issue-26655.rs4
-rw-r--r--src/test/run-pass/issue-27997.rs2
-rw-r--r--src/test/run-pass/nested-vec-3.rs2
-rw-r--r--src/test/run-pass/panic-handler-chain.rs3
-rw-r--r--src/test/run-pass/panic-handler-set-twice.rs3
-rw-r--r--src/test/run-pass/struct-order-of-eval-3.rs2
-rw-r--r--src/test/run-pass/struct-order-of-eval-4.rs2
-rw-r--r--src/test/run-pass/vector-sort-panic-safe.rs2
-rw-r--r--src/test/ui/span/dropck_arr_cycle_checked.rs2
-rw-r--r--src/test/ui/span/dropck_vec_cycle_checked.rs2
-rw-r--r--src/test/ui/span/vec-must-not-hide-type-from-dropck.rs2
m---------src/tools/rls0
60 files changed, 311 insertions, 101 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index 79822675364..c3cf9023b95 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -1346,7 +1346,7 @@ dependencies = [
  "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "racer 2.0.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "rls-analysis 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "rls-analysis 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1360,7 +1360,7 @@ dependencies = [
 
 [[package]]
 name = "rls-analysis"
-version = "0.6.5"
+version = "0.6.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2555,7 +2555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b"
 "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
 "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db"
-"checksum rls-analysis 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d2cb40c0371765897ae428b5706bb17135705ad4f6d1b8b6afbaabcf8c9b5cff"
+"checksum rls-analysis 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4302cc8291570d7f817945845d8c01756e833dbc93c0a87d4f6c9a0b0b7992f1"
 "checksum rls-data 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "11d339f1888e33e74d8032de0f83c40b2bdaaaf04a8cfc03b32186c3481fb534"
 "checksum rls-rustc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b21ea952e9bf1569929abf1bb920262cde04b7b1b26d8e0260286302807299d2"
 "checksum rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d7c7046dc6a92f2ae02ed302746db4382e75131b9ce20ce967259f6b5867a6a"
diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs
index e0a3b8d52f4..b9c5ff10f87 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -329,6 +329,7 @@ impl<T> Cell<T> {
     /// let c = Cell::new(5);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_cell_new"))]
     #[inline]
     pub const fn new(value: T) -> Cell<T> {
         Cell {
@@ -543,6 +544,7 @@ impl<T> RefCell<T> {
     /// let c = RefCell::new(5);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_refcell_new"))]
     #[inline]
     pub const fn new(value: T) -> RefCell<T> {
         RefCell {
@@ -1188,6 +1190,7 @@ impl<T> UnsafeCell<T> {
     /// let uc = UnsafeCell::new(5);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_unsafe_cell_new"))]
     #[inline]
     pub const fn new(value: T) -> UnsafeCell<T> {
         UnsafeCell { value: value }
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index c270c6ae0db..69612bd2a32 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -85,12 +85,30 @@
 #![feature(prelude_import)]
 #![feature(repr_simd, platform_intrinsics)]
 #![feature(rustc_attrs)]
+#![cfg_attr(not(stage0), feature(rustc_const_unstable))]
 #![feature(specialization)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 
+#![cfg_attr(not(stage0), feature(const_min_value))]
+#![cfg_attr(not(stage0), feature(const_max_value))]
+#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_isize_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_usize_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_i8_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_u8_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_i16_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_u16_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_i32_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_u32_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_i64_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_u64_new))]
+#![cfg_attr(not(stage0), feature(const_unsafe_cell_new))]
+#![cfg_attr(not(stage0), feature(const_cell_new))]
+#![cfg_attr(not(stage0), feature(const_nonzero_new))]
+
 #[prelude_import]
 #[allow(unused)]
 use prelude::v1::*;
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index bae1f4dee14..3e24623dad8 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -189,6 +189,7 @@ pub fn forget<T>(t: T) {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_size_of"))]
 pub const fn size_of<T>() -> usize {
     unsafe { intrinsics::size_of::<T>() }
 }
@@ -280,6 +281,7 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_align_of"))]
 pub const fn align_of<T>() -> usize {
     unsafe { intrinsics::min_align_of::<T>() }
 }
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index 3ff1068b937..f075d825f5d 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -68,6 +68,10 @@ pub struct NonZero<T: Zeroable>(T);
 impl<T: Zeroable> NonZero<T> {
     /// Creates an instance of NonZero with the provided value.
     /// You must indeed ensure that the value is actually "non-zero".
+    #[unstable(feature = "nonzero",
+               reason = "needs an RFC to flesh out the design",
+               issue = "27730")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_nonzero_new"))]
     #[inline]
     pub const unsafe fn new_unchecked(inner: T) -> Self {
         NonZero(inner)
diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs
index c5175287ccf..bf31deae7a6 100644
--- a/src/libcore/num/mod.rs
+++ b/src/libcore/num/mod.rs
@@ -109,6 +109,7 @@ macro_rules! int_impl {
         /// assert_eq!(i8::min_value(), -128);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_min_value"))]
         #[inline]
         pub const fn min_value() -> Self {
             !0 ^ ((!0 as $UnsignedT) >> 1) as Self
@@ -122,6 +123,7 @@ macro_rules! int_impl {
         /// assert_eq!(i8::max_value(), 127);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_max_value"))]
         #[inline]
         pub const fn max_value() -> Self {
             !Self::min_value()
@@ -1280,6 +1282,7 @@ macro_rules! uint_impl {
         /// assert_eq!(u8::min_value(), 0);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_min_value"))]
         #[inline]
         pub const fn min_value() -> Self { 0 }
 
@@ -1291,6 +1294,7 @@ macro_rules! uint_impl {
         /// assert_eq!(u8::max_value(), 255);
         /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
+        #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_max_value"))]
         #[inline]
         pub const fn max_value() -> Self { !0 }
 
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 2e42e0dfd55..20aa881f4bc 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -76,6 +76,7 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_null"))]
 pub const fn null<T>() -> *const T { 0 as *const T }
 
 /// Creates a null mutable raw pointer.
@@ -90,6 +91,7 @@ pub const fn null<T>() -> *const T { 0 as *const T }
 /// ```
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_null_mut"))]
 pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
 
 /// Swaps the values at two mutable locations of the same type, without
@@ -1097,6 +1099,8 @@ impl<T: ?Sized> Unique<T> {
     /// # Safety
     ///
     /// `ptr` must be non-null.
+    #[unstable(feature = "unique", issue = "27730")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_unique_new"))]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         Unique { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
     }
@@ -1230,6 +1234,8 @@ impl<T: ?Sized> Shared<T> {
     /// # Safety
     ///
     /// `ptr` must be non-null.
+    #[unstable(feature = "shared", issue = "27730")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_shared_new"))]
     pub const unsafe fn new_unchecked(ptr: *mut T) -> Self {
         Shared { pointer: NonZero::new_unchecked(ptr), _marker: PhantomData }
     }
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 510e01db0e9..09f3586a8c9 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -241,6 +241,7 @@ impl AtomicBool {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_atomic_bool_new"))]
     pub const fn new(v: bool) -> AtomicBool {
         AtomicBool { v: UnsafeCell::new(v as u8) }
     }
@@ -649,6 +650,7 @@ impl<T> AtomicPtr<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_atomic_ptr_new"))]
     pub const fn new(p: *mut T) -> AtomicPtr<T> {
         AtomicPtr { p: UnsafeCell::new(p) }
     }
@@ -920,7 +922,7 @@ impl<T> AtomicPtr<T> {
 
 #[cfg(target_has_atomic = "ptr")]
 macro_rules! atomic_int {
-    ($stable:meta,
+    ($stable:meta, $const_unstable:meta,
      $stable_cxchg:meta,
      $stable_debug:meta,
      $stable_access:meta,
@@ -969,6 +971,7 @@ macro_rules! atomic_int {
             /// ```
             #[inline]
             #[$stable]
+            #[cfg_attr(not(stage0), $const_unstable)]
             pub const fn new(v: $int_type) -> Self {
                 $atomic_type {v: UnsafeCell::new(v)}
             }
@@ -1332,6 +1335,7 @@ macro_rules! atomic_int {
 #[cfg(target_has_atomic = "8")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_i8_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1340,6 +1344,7 @@ atomic_int! {
 #[cfg(target_has_atomic = "8")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_u8_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1348,6 +1353,7 @@ atomic_int! {
 #[cfg(target_has_atomic = "16")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_i16_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1356,6 +1362,7 @@ atomic_int! {
 #[cfg(target_has_atomic = "16")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_u16_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1364,6 +1371,7 @@ atomic_int! {
 #[cfg(target_has_atomic = "32")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_i32_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1372,6 +1380,7 @@ atomic_int! {
 #[cfg(target_has_atomic = "32")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_u32_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1380,6 +1389,7 @@ atomic_int! {
 #[cfg(target_has_atomic = "64")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_i64_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1388,6 +1398,7 @@ atomic_int! {
 #[cfg(target_has_atomic = "64")]
 atomic_int! {
     unstable(feature = "integer_atomics", issue = "32976"),
+    rustc_const_unstable(feature = "const_atomic_u64_new"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
     unstable(feature = "integer_atomics", issue = "32976"),
@@ -1396,6 +1407,7 @@ atomic_int! {
 #[cfg(target_has_atomic = "ptr")]
 atomic_int!{
     stable(feature = "rust1", since = "1.0.0"),
+    rustc_const_unstable(feature = "const_atomic_isize_new"),
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
@@ -1404,6 +1416,7 @@ atomic_int!{
 #[cfg(target_has_atomic = "ptr")]
 atomic_int!{
     stable(feature = "rust1", since = "1.0.0"),
+    rustc_const_unstable(feature = "const_atomic_usize_new"),
     stable(feature = "extended_compare_and_swap", since = "1.10.0"),
     stable(feature = "atomic_debug", since = "1.3.0"),
     stable(feature = "atomic_access", since = "1.15.0"),
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index ab2022b1824..ce4d14b222c 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -11,7 +11,6 @@
 #![deny(warnings)]
 
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(core_float)]
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
@@ -42,6 +41,10 @@
 #![feature(try_from)]
 #![feature(unique)]
 
+#![feature(const_atomic_bool_new)]
+#![feature(const_atomic_usize_new)]
+#![feature(const_atomic_isize_new)]
+
 extern crate core;
 extern crate test;
 extern crate rand;
diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs
index b827284271e..e52be70190c 100644
--- a/src/librustc/ich/impls_syntax.rs
+++ b/src/librustc/ich/impls_syntax.rs
@@ -81,7 +81,12 @@ impl_stable_hash_for!(enum ::syntax::abi::Abi {
 });
 
 impl_stable_hash_for!(struct ::syntax::attr::Deprecation { since, note });
-impl_stable_hash_for!(struct ::syntax::attr::Stability { level, feature, rustc_depr });
+impl_stable_hash_for!(struct ::syntax::attr::Stability {
+    level,
+    feature,
+    rustc_depr,
+    rustc_const_unstable
+});
 
 impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>>
 for ::syntax::attr::StabilityLevel {
@@ -102,6 +107,7 @@ for ::syntax::attr::StabilityLevel {
 }
 
 impl_stable_hash_for!(struct ::syntax::attr::RustcDeprecation { since, reason });
+impl_stable_hash_for!(struct ::syntax::attr::RustcConstUnstable { feature });
 
 
 impl_stable_hash_for!(enum ::syntax::attr::IntType {
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 82f01c36fee..df97f2fb8bc 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -22,7 +22,6 @@
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(conservative_impl_trait)]
-#![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(i128_type)]
 #![cfg_attr(windows, feature(libc))]
@@ -36,6 +35,9 @@
 #![feature(trace_macros)]
 #![feature(test)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
+
 #![recursion_limit="256"]
 
 extern crate arena;
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 5ca235b2ad3..977102ec1ad 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -427,6 +427,7 @@ impl<'a, 'tcx> Index<'tcx> {
                     },
                     feature: Symbol::intern("rustc_private"),
                     rustc_depr: None,
+                    rustc_const_unstable: None,
                 });
                 annotator.parent_stab = Some(stability);
             }
diff --git a/src/librustc_apfloat/lib.rs b/src/librustc_apfloat/lib.rs
index d4a02065761..c13141008a4 100644
--- a/src/librustc_apfloat/lib.rs
+++ b/src/librustc_apfloat/lib.rs
@@ -45,11 +45,14 @@
 #![deny(warnings)]
 #![forbid(unsafe_code)]
 
-#![feature(const_fn)]
 #![feature(i128_type)]
 #![feature(slice_patterns)]
 #![feature(try_from)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_min_value))]
+#![cfg_attr(not(stage0), feature(const_max_value))]
+
 #[macro_use]
 extern crate rustc_bitflags;
 
diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs
index 9fedee80d46..0c3606cab10 100644
--- a/src/librustc_const_eval/lib.rs
+++ b/src/librustc_const_eval/lib.rs
@@ -23,9 +23,11 @@
 #![feature(slice_patterns)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(i128_type)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_min_value))]
+
 extern crate arena;
 #[macro_use] extern crate syntax;
 #[macro_use] extern crate log;
diff --git a/src/librustc_const_math/lib.rs b/src/librustc_const_math/lib.rs
index 93b70ef8e4a..0533f10104a 100644
--- a/src/librustc_const_math/lib.rs
+++ b/src/librustc_const_math/lib.rs
@@ -19,10 +19,13 @@
       html_root_url = "https://doc.rust-lang.org/nightly/")]
 #![deny(warnings)]
 
-#![feature(const_fn)]
 #![feature(i128)]
 #![feature(i128_type)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_min_value))]
+#![cfg_attr(not(stage0), feature(const_max_value))]
+
 extern crate rustc_apfloat;
 
 extern crate syntax;
diff --git a/src/librustc_mir/diagnostics.rs b/src/librustc_mir/diagnostics.rs
index 4b71a429f84..26436d54ac8 100644
--- a/src/librustc_mir/diagnostics.rs
+++ b/src/librustc_mir/diagnostics.rs
@@ -384,7 +384,7 @@ static B: &'static AtomicUsize = &A; // ok!
 You can also have this error while using a cell type:
 
 ```compile_fail,E0492
-#![feature(const_fn)]
+#![feature(const_cell_new)]
 
 use std::cell::Cell;
 
@@ -412,7 +412,7 @@ However, if you still wish to use these types, you can achieve this by an unsafe
 wrapper:
 
 ```
-#![feature(const_fn)]
+#![feature(const_cell_new)]
 
 use std::cell::Cell;
 use std::marker::Sync;
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index f8c26dc99c6..fa6a98224ee 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -30,6 +30,7 @@ use rustc::mir::transform::{MirPass, MirSource};
 use rustc::mir::visit::{LvalueContext, Visitor};
 use rustc::middle::lang_items;
 use syntax::abi::Abi;
+use syntax::attr;
 use syntax::feature_gate::UnstableFeatures;
 use syntax_pos::{Span, DUMMY_SP};
 
@@ -713,14 +714,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             self.visit_operand(func, location);
 
             let fn_ty = func.ty(self.mir, self.tcx);
-            let (mut is_shuffle, mut is_const_fn) = (false, false);
+            let (mut is_shuffle, mut is_const_fn) = (false, None);
             if let ty::TyFnDef(def_id, _) = fn_ty.sty {
                 match self.tcx.fn_sig(def_id).abi() {
                     Abi::RustIntrinsic |
                     Abi::PlatformIntrinsic => {
                         assert!(!self.tcx.is_const_fn(def_id));
                         match &self.tcx.item_name(def_id)[..] {
-                            "size_of" | "min_align_of" => is_const_fn = true,
+                            "size_of" | "min_align_of" => is_const_fn = Some(def_id),
 
                             name if name.starts_with("simd_shuffle") => {
                                 is_shuffle = true;
@@ -730,7 +731,9 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                         }
                     }
                     _ => {
-                        is_const_fn = self.tcx.is_const_fn(def_id);
+                        if self.tcx.is_const_fn(def_id) {
+                            is_const_fn = Some(def_id);
+                        }
                     }
                 }
             }
@@ -751,25 +754,38 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             }
 
             // Const fn calls.
-            if is_const_fn {
-                // We are in a const or static initializer,
-                if self.mode != Mode::Fn &&
-
-                    // feature-gate is not enabled,
-                    !self.tcx.sess.features.borrow().const_fn &&
-
-                    // this doesn't come from a crate with the feature-gate enabled,
-                    self.def_id.is_local() &&
-
-                    // this doesn't come from a macro that has #[allow_internal_unstable]
-                    !self.span.allows_unstable()
-                {
-                    let mut err = self.tcx.sess.struct_span_err(self.span,
-                        "const fns are an unstable feature");
-                    help!(&mut err,
-                          "in Nightly builds, add `#![feature(const_fn)]` \
-                           to the crate attributes to enable");
-                    err.emit();
+            if let Some(def_id) = is_const_fn {
+                // find corresponding rustc_const_unstable feature
+                if let Some(&attr::Stability {
+                    rustc_const_unstable: Some(attr::RustcConstUnstable {
+                        feature: ref feature_name
+                    }),
+                .. }) = self.tcx.lookup_stability(def_id) {
+
+                    // We are in a const or static initializer,
+                    if self.mode != Mode::Fn &&
+
+                        // feature-gate is not enabled,
+                        !self.tcx.sess.features.borrow()
+                            .declared_lib_features
+                            .iter()
+                            .any(|&(ref sym, _)| sym == feature_name) &&
+
+                        // this doesn't come from a crate with the feature-gate enabled,
+                        self.def_id.is_local() &&
+
+                        // this doesn't come from a macro that has #[allow_internal_unstable]
+                        !self.span.allows_unstable()
+                    {
+                        let mut err = self.tcx.sess.struct_span_err(self.span,
+                            &format!("`{}` is not yet stable as a const fn",
+                                     self.tcx.item_path_str(def_id)));
+                        help!(&mut err,
+                              "in Nightly builds, add `#![feature({})]` \
+                               to the crate attributes to enable",
+                              feature_name);
+                        err.emit();
+                    }
                 }
             } else {
                 self.qualif = Qualif::NOT_CONST;
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index 63fd37c2b98..256200a6e95 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -21,7 +21,6 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(i128_type)]
@@ -31,6 +30,10 @@
 #![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
+#![cfg_attr(not(stage0), feature(const_once_new))]
+
 use rustc::dep_graph::WorkProduct;
 use syntax_pos::symbol::Symbol;
 
diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs
index 90e17906328..5e8abe59ad9 100644
--- a/src/librustc_trans_utils/lib.rs
+++ b/src/librustc_trans_utils/lib.rs
@@ -19,7 +19,6 @@
 
 #![feature(box_patterns)]
 #![feature(box_syntax)]
-#![feature(const_fn)]
 #![feature(custom_attribute)]
 #![allow(unused_attributes)]
 #![feature(i128_type)]
@@ -28,6 +27,8 @@
 #![feature(slice_patterns)]
 #![feature(conservative_impl_trait)]
 
+#![cfg_attr(stage0, feature(const_fn))]
+
 extern crate rustc;
 extern crate syntax;
 extern crate syntax_pos;
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index 33bf0d68126..aa1337a9da0 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -292,6 +292,7 @@
 #![feature(raw)]
 #![feature(repr_simd)]
 #![feature(rustc_attrs)]
+#![cfg_attr(not(stage0), feature(rustc_const_unstable))]
 #![feature(shared)]
 #![feature(sip_hash_13)]
 #![feature(slice_bytes)]
@@ -315,6 +316,17 @@
 #![feature(doc_cfg)]
 #![cfg_attr(test, feature(update_panic_count))]
 
+#![cfg_attr(not(stage0), feature(const_max_value))]
+#![cfg_attr(not(stage0), feature(const_atomic_bool_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_isize_new))]
+#![cfg_attr(not(stage0), feature(const_atomic_usize_new))]
+#![cfg_attr(all(not(stage0), windows), feature(const_atomic_ptr_new))]
+#![cfg_attr(not(stage0), feature(const_unsafe_cell_new))]
+#![cfg_attr(not(stage0), feature(const_cell_new))]
+#![cfg_attr(not(stage0), feature(const_once_new))]
+#![cfg_attr(not(stage0), feature(const_ptr_null))]
+#![cfg_attr(not(stage0), feature(const_ptr_null_mut))]
+
 #![default_lib_allocator]
 
 // Always use alloc_system during stage0 since we don't know if the alloc_*
diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs
index 403685a4b8e..015106fc2e5 100644
--- a/src/libstd/sync/once.rs
+++ b/src/libstd/sync/once.rs
@@ -156,6 +156,7 @@ struct Finish {
 impl Once {
     /// Creates a new `Once` value.
     #[stable(feature = "once_new", since = "1.2.0")]
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_once_new"))]
     pub const fn new() -> Once {
         Once {
             state: AtomicUsize::new(INCOMPLETE),
diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs
index adbbc1b0ac5..03907eed900 100644
--- a/src/libsyntax/attr.rs
+++ b/src/libsyntax/attr.rs
@@ -637,12 +637,13 @@ pub fn eval_condition<F>(cfg: &ast::MetaItem, sess: &ParseSess, eval: &mut F)
     }
 }
 
-/// Represents the #[stable], #[unstable] and #[rustc_deprecated] attributes.
+/// Represents the #[stable], #[unstable], #[rustc_{deprecated,const_unstable}] attributes.
 #[derive(RustcEncodable, RustcDecodable, Clone, Debug, PartialEq, Eq, Hash)]
 pub struct Stability {
     pub level: StabilityLevel,
     pub feature: Symbol,
     pub rustc_depr: Option<RustcDeprecation>,
+    pub rustc_const_unstable: Option<RustcConstUnstable>,
 }
 
 /// The available stability levels.
@@ -660,6 +661,11 @@ pub struct RustcDeprecation {
 }
 
 #[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
+pub struct RustcConstUnstable {
+    pub feature: Symbol,
+}
+
+#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Clone, Debug, Eq, Hash)]
 pub struct Deprecation {
     pub since: Option<Symbol>,
     pub note: Option<Symbol>,
@@ -678,9 +684,15 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
 {
     let mut stab: Option<Stability> = None;
     let mut rustc_depr: Option<RustcDeprecation> = None;
+    let mut rustc_const_unstable: Option<RustcConstUnstable> = None;
 
     'outer: for attr in attrs_iter {
-        if attr.path != "rustc_deprecated" && attr.path != "unstable" && attr.path != "stable" {
+        if ![
+            "rustc_deprecated",
+            "rustc_const_unstable",
+            "unstable",
+            "stable",
+        ].iter().any(|&s| attr.path == s) {
             continue // not a stability level
         }
 
@@ -703,21 +715,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                 }
             };
 
-            match &*meta.name.as_str() {
-                "rustc_deprecated" => {
-                    if rustc_depr.is_some() {
-                        span_err!(diagnostic, item_sp, E0540,
-                                  "multiple rustc_deprecated attributes");
-                        break
-                    }
-
-                    let mut since = None;
-                    let mut reason = None;
+            macro_rules! get_meta {
+                ($($name:ident),+) => {
+                    $(
+                        let mut $name = None;
+                    )+
                     for meta in metas {
                         if let Some(mi) = meta.meta_item() {
                             match &*mi.name().as_str() {
-                                "since" => if !get(mi, &mut since) { continue 'outer },
-                                "reason" => if !get(mi, &mut reason) { continue 'outer },
+                                $(
+                                    stringify!($name)
+                                        => if !get(mi, &mut $name) { continue 'outer },
+                                )+
                                 _ => {
                                     handle_errors(diagnostic, mi.span,
                                                   AttrError::UnknownMetaItem(mi.name()));
@@ -729,6 +738,18 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                             continue 'outer
                         }
                     }
+                }
+            }
+
+            match &*meta.name.as_str() {
+                "rustc_deprecated" => {
+                    if rustc_depr.is_some() {
+                        span_err!(diagnostic, item_sp, E0540,
+                                  "multiple rustc_deprecated attributes");
+                        continue 'outer
+                    }
+
+                    get_meta!(since, reason);
 
                     match (since, reason) {
                         (Some(since), Some(reason)) => {
@@ -747,6 +768,23 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                         }
                     }
                 }
+                "rustc_const_unstable" => {
+                    if rustc_const_unstable.is_some() {
+                        span_err!(diagnostic, item_sp, E0553,
+                                  "multiple rustc_const_unstable attributes");
+                        continue 'outer
+                    }
+
+                    get_meta!(feature);
+                    if let Some(feature) = feature {
+                        rustc_const_unstable = Some(RustcConstUnstable {
+                            feature
+                        });
+                    } else {
+                        span_err!(diagnostic, attr.span(), E0629, "missing 'feature'");
+                        continue
+                    }
+                }
                 "unstable" => {
                     if stab.is_some() {
                         handle_errors(diagnostic, attr.span(), AttrError::MultipleStabilityLevels);
@@ -791,6 +829,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                                 },
                                 feature,
                                 rustc_depr: None,
+                                rustc_const_unstable: None,
                             })
                         }
                         (None, _, _) => {
@@ -836,6 +875,7 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
                                 },
                                 feature,
                                 rustc_depr: None,
+                                rustc_const_unstable: None,
                             })
                         }
                         (None, _) => {
@@ -867,6 +907,17 @@ fn find_stability_generic<'a, I>(diagnostic: &Handler,
         }
     }
 
+    // Merge the const-unstable info into the stability info
+    if let Some(rustc_const_unstable) = rustc_const_unstable {
+        if let Some(ref mut stab) = stab {
+            stab.rustc_const_unstable = Some(rustc_const_unstable);
+        } else {
+            span_err!(diagnostic, item_sp, E0630,
+                      "rustc_const_unstable attribute must be paired with \
+                       either stable or unstable attribute");
+        }
+    }
+
     stab
 }
 
diff --git a/src/libsyntax/diagnostic_list.rs b/src/libsyntax/diagnostic_list.rs
index 2ea3fe51d30..46dec73c962 100644
--- a/src/libsyntax/diagnostic_list.rs
+++ b/src/libsyntax/diagnostic_list.rs
@@ -357,8 +357,11 @@ register_diagnostics! {
     E0549, // rustc_deprecated attribute must be paired with either stable or unstable attribute
     E0550, // multiple deprecated attributes
     E0551, // incorrect meta item
+    E0553, // multiple rustc_const_unstable attributes
     E0555, // malformed feature attribute, expected #![feature(...)]
     E0556, // malformed feature, expected just one word
     E0584, // file for module `..` found at both .. and ..
     E0589, // invalid `repr(align)` attribute
+    E0629, // missing 'feature' (rustc_const_unstable)
+    E0630, // rustc_const_unstable attribute must be paired with stable/unstable attribute
 }
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 3d4ded2ae81..38e20b9fe40 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -137,6 +137,7 @@ declare_features! (
 
     // rustc internal
     (active, rustc_diagnostic_macros, "1.0.0", None),
+    (active, rustc_const_unstable, "1.0.0", None),
     (active, advanced_slice_patterns, "1.0.0", Some(23121)),
     (active, box_syntax, "1.0.0", Some(27779)),
     (active, placement_in_syntax, "1.0.0", Some(27779)),
@@ -622,6 +623,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
                                              "the `#[rustc_on_unimplemented]` attribute \
                                               is an experimental feature",
                                              cfg_fn!(on_unimplemented))),
+    ("rustc_const_unstable", Normal, Gated(Stability::Unstable,
+                                             "rustc_const_unstable",
+                                             "the `#[rustc_const_unstable]` attribute \
+                                              is an internal feature",
+                                             cfg_fn!(rustc_const_unstable))),
     ("global_allocator", Normal, Gated(Stability::Unstable,
                                        "global_allocator",
                                        "the `#[global_allocator]` attribute is \
diff --git a/src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs b/src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs
index 7de6e58c784..fa85432fb8e 100644
--- a/src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs
+++ b/src/test/compile-fail-fulldeps/dropck_tarena_cycle_checked.rs
@@ -16,7 +16,8 @@
 //  which is a reduction of this code to more directly show the reason
 //  for the error message we see here.)
 
-#![feature(const_fn, rustc_private)]
+#![feature(rustc_private)]
+#![feature(const_atomic_usize_new)]
 
 extern crate arena;
 
diff --git a/src/test/compile-fail/const-call.rs b/src/test/compile-fail/const-call.rs
index 0745ac02d07..18476494300 100644
--- a/src/test/compile-fail/const-call.rs
+++ b/src/test/compile-fail/const-call.rs
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
-
 fn f(x: usize) -> usize {
     x
 }
diff --git a/src/test/compile-fail/const-fn-feature-flags.rs b/src/test/compile-fail/const-fn-feature-flags.rs
new file mode 100644
index 00000000000..823cb89b365
--- /dev/null
+++ b/src/test/compile-fail/const-fn-feature-flags.rs
@@ -0,0 +1,24 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test use of const fns in std using individual feature gates.
+
+use std::cell::Cell;
+
+const CELL: Cell<i32> = Cell::new(42); //~ERROR not yet stable as a const fn
+    //~^HELP #![feature(const_cell_new)]
+
+fn main() {
+    let v = CELL.get();
+    CELL.set(v+1);
+
+    assert_eq!(CELL.get(), v);
+}
+
diff --git a/src/test/compile-fail/dropck_trait_cycle_checked.rs b/src/test/compile-fail/dropck_trait_cycle_checked.rs
index e701718028a..c0f0e3650d9 100644
--- a/src/test/compile-fail/dropck_trait_cycle_checked.rs
+++ b/src/test/compile-fail/dropck_trait_cycle_checked.rs
@@ -13,7 +13,7 @@
 //
 // (Compare against compile-fail/dropck_vec_cycle_checked.rs)
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::cell::Cell;
 use id::Id;
diff --git a/src/test/run-pass/const-fn-cross-crate.rs b/src/test/compile-fail/feature-gate-rustc_const_unstable.rs
index 7b4b751fd7f..38a3e15fd7e 100644
--- a/src/test/run-pass/const-fn-cross-crate.rs
+++ b/src/test/compile-fail/feature-gate-rustc_const_unstable.rs
@@ -8,19 +8,16 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:const_fn_lib.rs
-
-// A very basic test of const fn functionality.
+// Test internal const fn feature gate.
 
+#![feature(staged_api)]
 #![feature(const_fn)]
+//#![feature(rustc_const_unstable)]
 
-extern crate const_fn_lib;
-
-use const_fn_lib::foo;
-
-const FOO: usize = foo();
+#[stable(feature="zing", since="1.0.0")]
+#[rustc_const_unstable(feature="fzzzzzt")] //~ERROR internal feature
+pub const fn bazinga() {}
 
 fn main() {
-    assert_eq!(FOO, 22);
-    let _: [i32; foo()] = [42; 22];
 }
+
diff --git a/src/test/compile-fail/functional-struct-update-respects-privacy.rs b/src/test/compile-fail/functional-struct-update-respects-privacy.rs
index d2df0d9ef27..3f41401eb69 100644
--- a/src/test/compile-fail/functional-struct-update-respects-privacy.rs
+++ b/src/test/compile-fail/functional-struct-update-respects-privacy.rs
@@ -10,8 +10,6 @@
 
 // RFC 736 (and Issue 21407): functional struct update should respect privacy.
 
-#![feature(const_fn)]
-
 // The `foo` module attempts to maintains an invariant that each `S`
 // has a unique `u64` id.
 use self::foo::S;
diff --git a/src/test/compile-fail/issue-17718-const-borrow.rs b/src/test/compile-fail/issue-17718-const-borrow.rs
index 327b6946822..1464fcd9a1c 100644
--- a/src/test/compile-fail/issue-17718-const-borrow.rs
+++ b/src/test/compile-fail/issue-17718-const-borrow.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_unsafe_cell_new)]
 
 use std::cell::UnsafeCell;
 
diff --git a/src/test/compile-fail/issue-43733-2.rs b/src/test/compile-fail/issue-43733-2.rs
index 0fd31454596..1bf165c89d3 100644
--- a/src/test/compile-fail/issue-43733-2.rs
+++ b/src/test/compile-fail/issue-43733-2.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_fn, const_cell_new, const_unsafe_cell_new)]
 #![feature(cfg_target_thread_local, thread_local_internals)]
 
 // On platforms *without* `#[thread_local]`, use
diff --git a/src/test/compile-fail/issue-7364.rs b/src/test/compile-fail/issue-7364.rs
index bd32317ae78..ef53be75780 100644
--- a/src/test/compile-fail/issue-7364.rs
+++ b/src/test/compile-fail/issue-7364.rs
@@ -8,9 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(box_syntax)]
-#![feature(const_fn)]
-#![allow(warnings)]
+#![feature(box_syntax, const_refcell_new)]
 
 use std::cell::RefCell;
 
@@ -18,5 +16,6 @@ use std::cell::RefCell;
 static boxed: Box<RefCell<isize>> = box RefCell::new(0);
 //~^ ERROR allocations are not allowed in statics
 //~| ERROR `std::cell::RefCell<isize>: std::marker::Sync` is not satisfied
+//~| WARN unsupported constant expr
 
 fn main() { }
diff --git a/src/test/compile-fail/stability-attribute-sanity.rs b/src/test/compile-fail/stability-attribute-sanity.rs
index d35f2cbb584..263ac427b76 100644
--- a/src/test/compile-fail/stability-attribute-sanity.rs
+++ b/src/test/compile-fail/stability-attribute-sanity.rs
@@ -10,7 +10,7 @@
 
 // Various checks that stability attributes are used correctly, per RFC 507
 
-#![feature(staged_api)]
+#![feature(const_fn, staged_api, rustc_const_unstable)]
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
@@ -88,8 +88,11 @@ fn multiple3() { }
 #[stable(feature = "a", since = "b")]
 #[rustc_deprecated(since = "b", reason = "text")]
 #[rustc_deprecated(since = "b", reason = "text")]
-fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
+#[rustc_const_unstable(feature = "a")]
+#[rustc_const_unstable(feature = "b")]
+pub const fn multiple4() { } //~ ERROR multiple rustc_deprecated attributes [E0540]
 //~^ ERROR Invalid stability or deprecation version found
+//~| ERROR multiple rustc_const_unstable attributes
 
 #[rustc_deprecated(since = "a", reason = "text")]
 fn deprecated_without_unstable_or_stable() { }
diff --git a/src/test/debuginfo/constant-debug-locs.rs b/src/test/debuginfo/constant-debug-locs.rs
index 7b7bda30225..7a24510b7d4 100644
--- a/src/test/debuginfo/constant-debug-locs.rs
+++ b/src/test/debuginfo/constant-debug-locs.rs
@@ -15,7 +15,7 @@
 #![allow(dead_code, unused_variables)]
 #![feature(omit_gdb_pretty_printer_section)]
 #![omit_gdb_pretty_printer_section]
-#![feature(const_fn)]
+#![feature(const_unsafe_cell_new)]
 #![feature(static_mutex)]
 
 // This test makes sure that the compiler doesn't crash when trying to assign
diff --git a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
index 2815863fe99..439c1080f47 100644
--- a/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
+++ b/src/test/run-pass-valgrind/cast-enum-with-dtor.rs
@@ -11,7 +11,7 @@
 // no-prefer-dynamic
 
 #![allow(dead_code)]
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 // check dtor calling order when casting enums.
 
diff --git a/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs b/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs
index 8dc7d79ec2a..7cde780cc54 100644
--- a/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs
+++ b/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs
@@ -12,7 +12,7 @@
 // `Item` originates in a where-clause, not the declaration of
 // `T`. Issue #20300.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::marker::{PhantomData};
 use std::sync::atomic::{AtomicUsize};
diff --git a/src/test/run-pass/auxiliary/const_fn_lib.rs b/src/test/run-pass/auxiliary/const_fn_lib.rs
index b0d5a6b1272..be06e8dd570 100644
--- a/src/test/run-pass/auxiliary/const_fn_lib.rs
+++ b/src/test/run-pass/auxiliary/const_fn_lib.rs
@@ -13,4 +13,4 @@
 #![crate_type="rlib"]
 #![feature(const_fn)]
 
-pub const fn foo() -> usize { 22 } //~ ERROR const fn is unstable
+pub const fn foo() -> usize { 22 }
diff --git a/src/test/run-pass/auxiliary/issue-17718-aux.rs b/src/test/run-pass/auxiliary/issue-17718-aux.rs
index cf7fdd7f983..36891a1ecad 100644
--- a/src/test/run-pass/auxiliary/issue-17718-aux.rs
+++ b/src/test/run-pass/auxiliary/issue-17718-aux.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic;
 
diff --git a/src/test/run-pass/auxiliary/thread-local-extern-static.rs b/src/test/run-pass/auxiliary/thread-local-extern-static.rs
index e9457886be8..bce87ef5a26 100644
--- a/src/test/run-pass/auxiliary/thread-local-extern-static.rs
+++ b/src/test/run-pass/auxiliary/thread-local-extern-static.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![feature(cfg_target_thread_local, const_fn, thread_local)]
+#![feature(const_cell_new)]
 #![crate_type = "lib"]
 
 #[cfg(target_thread_local)]
diff --git a/src/test/run-pass/box-of-array-of-drop-1.rs b/src/test/run-pass/box-of-array-of-drop-1.rs
index a63a232e1b5..47b44863a74 100644
--- a/src/test/run-pass/box-of-array-of-drop-1.rs
+++ b/src/test/run-pass/box-of-array-of-drop-1.rs
@@ -13,7 +13,7 @@
 
 // ignore-emscripten no threads support
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::thread;
 use std::sync::atomic::{AtomicUsize, Ordering};
diff --git a/src/test/run-pass/box-of-array-of-drop-2.rs b/src/test/run-pass/box-of-array-of-drop-2.rs
index ca179429172..54be4955baf 100644
--- a/src/test/run-pass/box-of-array-of-drop-2.rs
+++ b/src/test/run-pass/box-of-array-of-drop-2.rs
@@ -13,7 +13,7 @@
 
 // ignore-emscripten no threads support
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::thread;
 use std::sync::atomic::{AtomicUsize, Ordering};
diff --git a/src/test/run-pass/const-fn-feature-flags.rs b/src/test/run-pass/const-fn-feature-flags.rs
new file mode 100644
index 00000000000..1e27a3edac8
--- /dev/null
+++ b/src/test/run-pass/const-fn-feature-flags.rs
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test use of const fns in std using individual feature gates.
+
+#![feature(const_cell_new)]
+
+use std::cell::Cell;
+
+const CELL: Cell<i32> = Cell::new(42);
+
+fn main() {
+    let v = CELL.get();
+    CELL.set(v+1);
+
+    assert_eq!(CELL.get(), v);
+}
+
diff --git a/src/test/compile-fail/const-fn-stability-calls.rs b/src/test/run-pass/const-fn-stability-calls.rs
index 609077663ef..c5f97d55c06 100644
--- a/src/test/compile-fail/const-fn-stability-calls.rs
+++ b/src/test/run-pass/const-fn-stability-calls.rs
@@ -16,8 +16,8 @@ extern crate const_fn_lib;
 
 use const_fn_lib::foo;
 
-static FOO: usize = foo(); //~ ERROR const fns are an unstable feature
-const BAR: usize = foo(); //~ ERROR const fns are an unstable feature
+static FOO: usize = foo();
+const BAR: usize = foo();
 
 macro_rules! constant {
     ($n:ident: $t:ty = $v:expr) => {
@@ -26,9 +26,9 @@ macro_rules! constant {
 }
 
 constant! {
-    BAZ: usize = foo() //~ ERROR const fns are an unstable feature
+    BAZ: usize = foo()
 }
 
 fn main() {
-//    let x: [usize; foo()] = [];
+    let x: [usize; foo()] = [42; foo()];
 }
diff --git a/src/test/run-pass/const-size_of-align_of.rs b/src/test/run-pass/const-size_of-align_of.rs
index 06fbe9bf4f6..d5547ea5add 100644
--- a/src/test/run-pass/const-size_of-align_of.rs
+++ b/src/test/run-pass/const-size_of-align_of.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_fn, const_size_of, const_align_of)]
 
 use std::mem;
 
diff --git a/src/test/run-pass/issue-17718-static-unsafe-interior.rs b/src/test/run-pass/issue-17718-static-unsafe-interior.rs
index 993e5e1c1e6..66f70cdaeb0 100644
--- a/src/test/run-pass/issue-17718-static-unsafe-interior.rs
+++ b/src/test/run-pass/issue-17718-static-unsafe-interior.rs
@@ -11,8 +11,7 @@
 // pretty-expanded FIXME #23616
 
 #![feature(core)]
-#![feature(const_fn)]
-
+#![feature(const_unsafe_cell_new)]
 
 use std::marker;
 use std::cell::UnsafeCell;
diff --git a/src/test/run-pass/issue-17718.rs b/src/test/run-pass/issue-17718.rs
index 744e63f159b..1b8fbc1ad2f 100644
--- a/src/test/run-pass/issue-17718.rs
+++ b/src/test/run-pass/issue-17718.rs
@@ -12,7 +12,7 @@
 
 
 #![feature(core)]
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 extern crate issue_17718_aux as other;
 
diff --git a/src/test/run-pass/issue-21486.rs b/src/test/run-pass/issue-21486.rs
index 699189a4e6a..23d06c4324d 100644
--- a/src/test/run-pass/issue-21486.rs
+++ b/src/test/run-pass/issue-21486.rs
@@ -12,7 +12,7 @@
 // created via FRU and control-flow breaks in the middle of
 // construction.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{Ordering, AtomicUsize};
 
diff --git a/src/test/run-pass/issue-26655.rs b/src/test/run-pass/issue-26655.rs
index 402460e7253..3e252b8629e 100644
--- a/src/test/run-pass/issue-26655.rs
+++ b/src/test/run-pass/issue-26655.rs
@@ -10,10 +10,10 @@
 
 // ignore-emscripten no threads support
 
-#![feature(const_fn)]
-
 // Check that the destructors of simple enums are run on unwinding
 
+#![feature(const_atomic_usize_new)]
+
 use std::sync::atomic::{Ordering, AtomicUsize};
 use std::thread;
 
diff --git a/src/test/run-pass/issue-27997.rs b/src/test/run-pass/issue-27997.rs
index cd81f689693..dab42e48e16 100644
--- a/src/test/run-pass/issue-27997.rs
+++ b/src/test/run-pass/issue-27997.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{Ordering, AtomicUsize};
 
diff --git a/src/test/run-pass/nested-vec-3.rs b/src/test/run-pass/nested-vec-3.rs
index 458b6c16e62..9141b5f29ce 100644
--- a/src/test/run-pass/nested-vec-3.rs
+++ b/src/test/run-pass/nested-vec-3.rs
@@ -14,7 +14,7 @@
 // the contents implement Drop and we hit a panic in the middle of
 // construction.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::thread;
 use std::sync::atomic::{AtomicUsize, Ordering};
diff --git a/src/test/run-pass/panic-handler-chain.rs b/src/test/run-pass/panic-handler-chain.rs
index 1ad43f5f17f..c5dc8ccd2ee 100644
--- a/src/test/run-pass/panic-handler-chain.rs
+++ b/src/test/run-pass/panic-handler-chain.rs
@@ -10,7 +10,8 @@
 
 // ignore-emscripten no threads support
 
-#![feature(panic_handler, const_fn, std_panic)]
+#![feature(panic_handler, std_panic)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{AtomicUsize, Ordering};
 use std::panic;
diff --git a/src/test/run-pass/panic-handler-set-twice.rs b/src/test/run-pass/panic-handler-set-twice.rs
index 196e08a63a7..8bf2683cd9f 100644
--- a/src/test/run-pass/panic-handler-set-twice.rs
+++ b/src/test/run-pass/panic-handler-set-twice.rs
@@ -7,7 +7,8 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
-#![feature(panic_handler, const_fn, std_panic)]
+#![feature(panic_handler, std_panic)]
+#![feature(const_atomic_usize_new)]
 
 // ignore-emscripten no threads support
 
diff --git a/src/test/run-pass/struct-order-of-eval-3.rs b/src/test/run-pass/struct-order-of-eval-3.rs
index b67eb205396..cf93133d205 100644
--- a/src/test/run-pass/struct-order-of-eval-3.rs
+++ b/src/test/run-pass/struct-order-of-eval-3.rs
@@ -11,7 +11,7 @@
 // Checks that functional-record-update order-of-eval is as expected
 // even when no Drop-implementations are involved.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{Ordering, AtomicUsize};
 
diff --git a/src/test/run-pass/struct-order-of-eval-4.rs b/src/test/run-pass/struct-order-of-eval-4.rs
index 20d27d8b309..d442923478f 100644
--- a/src/test/run-pass/struct-order-of-eval-4.rs
+++ b/src/test/run-pass/struct-order-of-eval-4.rs
@@ -11,7 +11,7 @@
 // Checks that struct-literal expression order-of-eval is as expected
 // even when no Drop-implementations are involved.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::sync::atomic::{Ordering, AtomicUsize};
 
diff --git a/src/test/run-pass/vector-sort-panic-safe.rs b/src/test/run-pass/vector-sort-panic-safe.rs
index 4387a43f03b..c6a1859de30 100644
--- a/src/test/run-pass/vector-sort-panic-safe.rs
+++ b/src/test/run-pass/vector-sort-panic-safe.rs
@@ -10,9 +10,9 @@
 
 // ignore-emscripten no threads support
 
-#![feature(const_fn)]
 #![feature(rand)]
 #![feature(sort_unstable)]
+#![feature(const_atomic_usize_new)]
 
 use std::__rand::{thread_rng, Rng};
 use std::cell::Cell;
diff --git a/src/test/ui/span/dropck_arr_cycle_checked.rs b/src/test/ui/span/dropck_arr_cycle_checked.rs
index 8e8b3c24c76..995a198271c 100644
--- a/src/test/ui/span/dropck_arr_cycle_checked.rs
+++ b/src/test/ui/span/dropck_arr_cycle_checked.rs
@@ -13,7 +13,7 @@
 //
 // (Compare against compile-fail/dropck_vec_cycle_checked.rs)
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::cell::Cell;
 use id::Id;
diff --git a/src/test/ui/span/dropck_vec_cycle_checked.rs b/src/test/ui/span/dropck_vec_cycle_checked.rs
index 65db2a56b7d..5bcaa71f73c 100644
--- a/src/test/ui/span/dropck_vec_cycle_checked.rs
+++ b/src/test/ui/span/dropck_vec_cycle_checked.rs
@@ -12,7 +12,7 @@
 //
 // (Compare against compile-fail/dropck_arr_cycle_checked.rs)
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::cell::Cell;
 use id::Id;
diff --git a/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs b/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs
index 310ab20489a..d99f3bb19db 100644
--- a/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs
+++ b/src/test/ui/span/vec-must-not-hide-type-from-dropck.rs
@@ -23,7 +23,7 @@
 // conditions above to be satisfied, meaning that if the dropck is
 // sound, it should reject this code.
 
-#![feature(const_fn)]
+#![feature(const_atomic_usize_new)]
 
 use std::cell::Cell;
 use id::Id;
diff --git a/src/tools/rls b/src/tools/rls
-Subproject 8dd70945fb049df3f9dc7685cdc58d94e05e8ff
+Subproject 52d48656f93eeeb2c568e6c1048e64168e5b209