about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
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