about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-26 13:08:55 +0100
committerOliver Scherer <github35764891676564198441@oli-obk.de>2018-11-30 09:44:15 +0100
commit8937faa83795ccd55b19a5cb1869ce3b1097fe43 (patch)
tree5d0818f2625c8cfbf3c71113c734c5fcd9f48a67
parent866664c8bb1a3f1eb7fa60c8d8243535675ea78f (diff)
downloadrust-8937faa83795ccd55b19a5cb1869ce3b1097fe43.tar.gz
rust-8937faa83795ccd55b19a5cb1869ce3b1097fe43.zip
Reenable `const_let` feature gate
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs230
-rw-r--r--src/librustc_mir/transform/qualify_min_const_fn.rs17
-rw-r--r--src/libsyntax/feature_gate.rs3
-rw-r--r--src/test/run-pass/ctfe/const-block-non-item-statement-3.rs2
-rw-r--r--src/test/run-pass/ctfe/const-block-non-item-statement.rs2
-rw-r--r--src/test/run-pass/ctfe/locals-in-const-fn.rs2
-rw-r--r--src/test/ui/check-static-values-constraints.nll.stderr62
-rw-r--r--src/test/ui/check-static-values-constraints.rs7
-rw-r--r--src/test/ui/check-static-values-constraints.stderr62
-rw-r--r--src/test/ui/consts/const-block-non-item-statement-2.rs10
-rw-r--r--src/test/ui/consts/const-block-non-item-statement-2.stderr62
-rw-r--r--src/test/ui/consts/const-block-non-item-statement-3.rs6
-rw-r--r--src/test/ui/consts/const-block-non-item-statement-3.stderr35
-rw-r--r--src/test/ui/consts/const-block-non-item-statement.rs6
-rw-r--r--src/test/ui/consts/const-block-non-item-statement.stderr35
-rw-r--r--src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs3
-rw-r--r--src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr4
-rw-r--r--src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs1
-rw-r--r--src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr2
-rw-r--r--src/test/ui/consts/const-eval/const_let.rs2
-rw-r--r--src/test/ui/consts/const-eval/const_let.stderr4
-rw-r--r--src/test/ui/consts/const-eval/infinite_loop.rs2
-rw-r--r--src/test/ui/consts/const-eval/infinite_loop.stderr6
-rw-r--r--src/test/ui/consts/const-eval/issue-52475.rs2
-rw-r--r--src/test/ui/consts/const-eval/issue-52475.stderr6
-rw-r--r--src/test/ui/consts/const-eval/mod-static-with-const-fn.rs3
-rw-r--r--src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr4
-rw-r--r--src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr13
-rw-r--r--src/test/ui/consts/const-eval/ub-upvars.rs2
-rw-r--r--src/test/ui/consts/const-fn-destructuring-arg.rs14
-rw-r--r--src/test/ui/consts/const-fn-destructuring-arg.stderr35
-rw-r--r--src/test/ui/consts/const-fn-not-safe-for-const.rs8
-rw-r--r--src/test/ui/consts/const-fn-not-safe-for-const.stderr52
-rw-r--r--src/test/ui/consts/const_let_assign.rs2
-rw-r--r--src/test/ui/consts/const_let_assign2.rs3
-rw-r--r--src/test/ui/consts/const_let_assign3.rs3
-rw-r--r--src/test/ui/consts/const_let_assign3.stderr4
-rw-r--r--src/test/ui/consts/const_let_eq.rs2
-rw-r--r--src/test/ui/consts/const_short_circuit.rs4
-rw-r--r--src/test/ui/consts/dangling-alloc-id-ice.rs2
-rw-r--r--src/test/ui/consts/dangling-alloc-id-ice.stderr2
-rw-r--r--src/test/ui/consts/dangling_raw_ptr.rs2
-rw-r--r--src/test/ui/consts/dangling_raw_ptr.stderr2
-rw-r--r--src/test/ui/consts/issue-54224.rs5
-rw-r--r--src/test/ui/consts/issue-54224.stderr23
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr8
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.rs2
-rw-r--r--src/test/ui/consts/min_const_fn/min_const_fn.stderr8
-rw-r--r--src/test/ui/consts/min_const_fn/mutable_borrow.nll.stderr51
-rw-r--r--src/test/ui/consts/min_const_fn/mutable_borrow.rs34
-rw-r--r--src/test/ui/consts/min_const_fn/mutable_borrow.stderr55
-rw-r--r--src/test/ui/consts/partial_qualif.rs2
-rw-r--r--src/test/ui/consts/partial_qualif.stderr2
-rw-r--r--src/test/ui/consts/projection_qualif.rs4
-rw-r--r--src/test/ui/consts/projection_qualif.stderr6
-rw-r--r--src/test/ui/consts/promote_const_let.nll.stderr2
-rw-r--r--src/test/ui/consts/promote_const_let.rs2
-rw-r--r--src/test/ui/consts/promote_const_let.stderr2
-rw-r--r--src/test/ui/consts/qualif_overwrite.rs2
-rw-r--r--src/test/ui/consts/qualif_overwrite.stderr2
-rw-r--r--src/test/ui/consts/qualif_overwrite_2.rs2
-rw-r--r--src/test/ui/consts/qualif_overwrite_2.stderr2
-rw-r--r--src/test/ui/error-codes/E0010-teach.rs1
-rw-r--r--src/test/ui/error-codes/E0010-teach.stderr14
-rw-r--r--src/test/ui/error-codes/E0010.rs1
-rw-r--r--src/test/ui/error-codes/E0010.stderr11
-rw-r--r--src/test/ui/feature-gate-underscore_const_names.rs1
-rw-r--r--src/test/ui/feature-gate-underscore_const_names.stderr2
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_let.rs31
-rw-r--r--src/test/ui/issues/issue-18118.nll.stderr60
-rw-r--r--src/test/ui/issues/issue-18118.rs5
-rw-r--r--src/test/ui/issues/issue-18118.stderr60
-rw-r--r--src/test/ui/issues/issue-32829-2.rs13
-rw-r--r--src/test/ui/issues/issue-32829-2.stderr83
-rw-r--r--src/test/ui/issues/issue-37550.rs4
-rw-r--r--src/test/ui/issues/issue-37550.stderr6
-rw-r--r--src/test/ui/issues/issue-7364.rs1
-rw-r--r--src/test/ui/issues/issue-7364.stderr10
-rw-r--r--src/test/ui/static/static-mut-not-constant.rs1
-rw-r--r--src/test/ui/static/static-mut-not-constant.stderr11
-rw-r--r--src/test/ui/underscore_const_names.rs1
-rw-r--r--src/test/ui/write-to-static-mut-in-static.rs2
-rw-r--r--src/test/ui/write-to-static-mut-in-static.stderr4
83 files changed, 871 insertions, 395 deletions
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index d399543145d..0f174d6da1f 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -30,7 +30,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext, NonMutatingUs
 use rustc::middle::lang_items;
 use rustc_target::spec::abi::Abi;
 use syntax::ast::LitKind;
-use syntax::feature_gate::{UnstableFeatures, emit_feature_err, GateIssue};
+use syntax::feature_gate::{UnstableFeatures, feature_err, emit_feature_err, GateIssue};
 use syntax_pos::{Span, DUMMY_SP};
 
 use std::fmt;
@@ -114,6 +114,7 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     param_env: ty::ParamEnv<'tcx>,
     local_qualif: IndexVec<Local, Option<Qualif>>,
     qualif: Qualif,
+    const_fn_arg_vars: BitSet<Local>,
     temp_promotion_state: IndexVec<Local, TempState>,
     promotion_candidates: Vec<Candidate>
 }
@@ -148,6 +149,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
             param_env,
             local_qualif,
             qualif: Qualif::empty(),
+            const_fn_arg_vars: BitSet::new_empty(mir.local_decls.len()),
             temp_promotion_state: temps,
             promotion_candidates: vec![]
         }
@@ -176,6 +178,26 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
         }
     }
 
+    /// Error about extra statements in a constant.
+    fn statement_like(&mut self) {
+        self.add(Qualif::NOT_CONST);
+        if self.mode != Mode::Fn {
+            let mut err = feature_err(
+                &self.tcx.sess.parse_sess,
+                "const_let",
+                self.span,
+                GateIssue::Language,
+                &format!("statements in {}s are unstable", self.mode),
+            );
+            if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                err.note("Blocks in constants may only contain items (such as constant, function \
+                          definition, etc...) and a tail expression.");
+                err.help("To avoid it, you have to replace the non-item object.");
+            }
+            err.emit();
+        }
+    }
+
     /// Add the given qualification to self.qualif.
     fn add(&mut self, qualif: Qualif) {
         self.qualif = self.qualif | qualif;
@@ -221,46 +243,85 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
             return;
         }
 
-        let mut dest = dest;
-        let index = loop {
-            match dest {
-                Place::Local(index) => break *index,
-                // projections are transparent for assignments
-                // we qualify the entire destination at once, even if just a field would have
-                // stricter qualification
-                Place::Projection(proj) => {
-                    // Catch more errors in the destination. `visit_place` also checks various
-                    // projection rules like union field access and raw pointer deref
-                    self.visit_place(
-                        dest,
-                        PlaceContext::MutatingUse(MutatingUseContext::Store),
-                        location
-                    );
-                    dest = &proj.base;
-                },
-                Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"),
-                Place::Static(..) => {
-                    // Catch more errors in the destination. `visit_place` also checks that we
-                    // do not try to access statics from constants or try to mutate statics
-                    self.visit_place(
-                        dest,
-                        PlaceContext::MutatingUse(MutatingUseContext::Store),
-                        location
-                    );
-                    return;
+        if self.const_let_allowed() {
+            let mut dest = dest;
+            let index = loop {
+                match dest {
+                    // with `const_let` active, we treat all locals equal
+                    Place::Local(index) => break *index,
+                    // projections are transparent for assignments
+                    // we qualify the entire destination at once, even if just a field would have
+                    // stricter qualification
+                    Place::Projection(proj) => {
+                        // Catch more errors in the destination. `visit_place` also checks various
+                        // projection rules like union field access and raw pointer deref
+                        self.visit_place(
+                            dest,
+                            PlaceContext::MutatingUse(MutatingUseContext::Store),
+                            location
+                        );
+                        dest = &proj.base;
+                    },
+                    Place::Promoted(..) => bug!("promoteds don't exist yet during promotion"),
+                    Place::Static(..) => {
+                        // Catch more errors in the destination. `visit_place` also checks that we
+                        // do not try to access statics from constants or try to mutate statics
+                        self.visit_place(
+                            dest,
+                            PlaceContext::MutatingUse(MutatingUseContext::Store),
+                            location
+                        );
+                        return;
+                    }
                 }
+            };
+            debug!("store to var {:?}", index);
+            match &mut self.local_qualif[index] {
+                // this is overly restrictive, because even full assignments do not clear the qualif
+                // While we could special case full assignments, this would be inconsistent with
+                // aggregates where we overwrite all fields via assignments, which would not get
+                // that feature.
+                Some(ref mut qualif) => *qualif = *qualif | self.qualif,
+                // insert new qualification
+                qualif @ None => *qualif = Some(self.qualif),
             }
-        };
-        debug!("store to var {:?}", index);
-        match &mut self.local_qualif[index] {
-            // this is overly restrictive, because even full assignments do not clear the qualif
-            // While we could special case full assignments, this would be inconsistent with
-            // aggregates where we overwrite all fields via assignments, which would not get
-            // that feature.
-            Some(ref mut qualif) => *qualif = *qualif | self.qualif,
-            // insert new qualification
-            qualif @ None => *qualif = Some(self.qualif),
+            return;
         }
+
+        match *dest {
+            Place::Local(index) if self.mir.local_kind(index) == LocalKind::Temp ||
+                                   self.mir.local_kind(index) == LocalKind::ReturnPointer => {
+                debug!("store to {:?} (temp or return pointer)", index);
+                store(&mut self.local_qualif[index])
+            }
+
+            Place::Projection(box Projection {
+                base: Place::Local(index),
+                elem: ProjectionElem::Deref
+            }) if self.mir.local_kind(index) == LocalKind::Temp
+               && self.mir.local_decls[index].ty.is_box()
+               && self.local_qualif[index].map_or(false, |qualif| {
+                    qualif.contains(Qualif::NOT_CONST)
+               }) => {
+                // Part of `box expr`, we should've errored
+                // already for the Box allocation Rvalue.
+            }
+
+            // This must be an explicit assignment.
+            _ => {
+                // Catch more errors in the destination.
+                self.visit_place(
+                    dest,
+                    PlaceContext::MutatingUse(MutatingUseContext::Store),
+                    location
+                );
+                self.statement_like();
+            }
+        }
+    }
+
+    fn const_let_allowed(&self) -> bool {
+        self.tcx.features().const_let
     }
 
     /// Qualify a whole const, static initializer or const fn.
@@ -299,7 +360,48 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
                 TerminatorKind::FalseEdges { .. } |
                 TerminatorKind::FalseUnwind { .. } => None,
 
-                TerminatorKind::Return => break,
+                TerminatorKind::Return => {
+                    if !self.const_let_allowed() {
+                        // Check for unused values. This usually means
+                        // there are extra statements in the AST.
+                        for temp in mir.temps_iter() {
+                            if self.local_qualif[temp].is_none() {
+                                continue;
+                            }
+
+                            let state = self.temp_promotion_state[temp];
+                            if let TempState::Defined { location, uses: 0 } = state {
+                                let data = &mir[location.block];
+                                let stmt_idx = location.statement_index;
+
+                                // Get the span for the initialization.
+                                let source_info = if stmt_idx < data.statements.len() {
+                                    data.statements[stmt_idx].source_info
+                                } else {
+                                    data.terminator().source_info
+                                };
+                                self.span = source_info.span;
+
+                                // Treat this as a statement in the AST.
+                                self.statement_like();
+                            }
+                        }
+
+                        // Make sure there are no extra unassigned variables.
+                        self.qualif = Qualif::NOT_CONST;
+                        for index in mir.vars_iter() {
+                            if !self.const_fn_arg_vars.contains(index) {
+                                debug!("unassigned variable {:?}", index);
+                                self.assign(&Place::Local(index), Location {
+                                    block: bb,
+                                    statement_index: usize::MAX,
+                                });
+                            }
+                        }
+                    }
+
+                    break;
+                }
             };
 
             match target {
@@ -366,6 +468,14 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             LocalKind::ReturnPointer => {
                 self.not_const();
             }
+            LocalKind::Var if !self.const_let_allowed() => {
+                if self.mode != Mode::Fn {
+                    emit_feature_err(&self.tcx.sess.parse_sess, "const_let",
+                                    self.span, GateIssue::Language,
+                                    &format!("let bindings in {}s are unstable",self.mode));
+                }
+                self.add(Qualif::NOT_CONST);
+            }
             LocalKind::Var |
             LocalKind::Arg |
             LocalKind::Temp => {
@@ -448,6 +558,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                         ProjectionElem::Deref => {
                             if context.is_mutating_use() {
                                 this.not_const()
+                            } else {
+                                this.qualif = Qualif::NOT_CONST;
                             }
                             let base_ty = proj.base.ty(this.mir, this.tcx).to_ty(this.tcx);
                             match this.mode {
@@ -1050,6 +1162,46 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
         debug!("visit_assign: dest={:?} rvalue={:?} location={:?}", dest, rvalue, location);
         self.visit_rvalue(rvalue, location);
 
+        // Check the allowed const fn argument forms.
+        if let (Mode::ConstFn, &Place::Local(index)) = (self.mode, dest) {
+            if self.mir.local_kind(index) == LocalKind::Var &&
+               self.const_fn_arg_vars.insert(index) &&
+               !self.tcx.sess.features_untracked().const_let {
+                // Direct use of an argument is permitted.
+                match *rvalue {
+                    Rvalue::Use(Operand::Copy(Place::Local(local))) |
+                    Rvalue::Use(Operand::Move(Place::Local(local))) => {
+                        if self.mir.local_kind(local) == LocalKind::Arg {
+                            return;
+                        }
+                    }
+                    _ => {}
+                }
+                // Avoid a generic error for other uses of arguments.
+                if self.qualif.contains(Qualif::FN_ARGUMENT) {
+                    let decl = &self.mir.local_decls[index];
+                    let mut err = feature_err(
+                        &self.tcx.sess.parse_sess,
+                        "const_let",
+                        decl.source_info.span,
+                        GateIssue::Language,
+                        "arguments of constant functions can only be immutable by-value bindings"
+                    );
+                    if self.tcx.sess.teach(&err.get_code().unwrap()) {
+                        err.note("Constant functions are not allowed to mutate anything. Thus, \
+                                  binding to an argument with a mutable pattern is not allowed.");
+                        err.note("Remove any mutable bindings from the argument list to fix this \
+                                  error. In case you need to mutate the argument, try lazily \
+                                  initializing a global variable instead of using a const fn, or \
+                                  refactoring the code to a functional style to avoid mutation if \
+                                  possible.");
+                    }
+                    err.emit();
+                    return;
+                }
+            }
+        }
+
         self.assign(dest, location);
     }
 
diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs
index 5729775e15d..9e5d75a746e 100644
--- a/src/librustc_mir/transform/qualify_min_const_fn.rs
+++ b/src/librustc_mir/transform/qualify_min_const_fn.rs
@@ -64,6 +64,12 @@ pub fn is_min_const_fn(
         }
     }
 
+    for local in mir.vars_iter() {
+        return Err((
+            mir.local_decls[local].source_info.span,
+            "local variables in const fn are unstable".into(),
+        ));
+    }
     for local in &mir.local_decls {
         check_ty(tcx, local.ty, local.source_info.span)?;
     }
@@ -264,8 +270,15 @@ fn check_place(
     mode: PlaceMode,
 ) -> McfResult {
     match place {
-        // assignments to locals, arguments, temporaries or the return slot are fine
-        Place::Local(_) => Ok(()),
+        Place::Local(l) => match mode {
+            PlaceMode::Assign => match mir.local_kind(*l) {
+                LocalKind::Temp | LocalKind::ReturnPointer => Ok(()),
+                LocalKind::Arg | LocalKind::Var => {
+                    Err((span, "assignments in const fn are unstable".into()))
+                }
+            },
+            PlaceMode::Read => Ok(()),
+        },
         // promoteds are always fine, they are essentially constants
         Place::Promoted(_) => Ok(()),
         Place::Static(_) => Err((span, "cannot access `static` items in const fn".into())),
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 586659ecd9c..3bc34917051 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -209,6 +209,9 @@ declare_features! (
     // Allows the definition of `const fn` functions with some advanced features.
     (active, const_fn, "1.2.0", Some(24111), None),
 
+    // Allows let bindings and destructuring in `const fn` functions and constants.
+    (active, const_let, "1.22.1", Some(48821), None),
+
     // Allows accessing fields of unions inside const fn.
     (active, const_fn_union, "1.27.0", Some(51909), None),
 
diff --git a/src/test/run-pass/ctfe/const-block-non-item-statement-3.rs b/src/test/run-pass/ctfe/const-block-non-item-statement-3.rs
index 997476853ec..0fcf9a5acbd 100644
--- a/src/test/run-pass/ctfe/const-block-non-item-statement-3.rs
+++ b/src/test/run-pass/ctfe/const-block-non-item-statement-3.rs
@@ -11,6 +11,8 @@
 // run-pass
 #![allow(dead_code)]
 
+#![feature(const_let)]
+
 type Array = [u32; {  let x = 2; 5 }];
 
 pub fn main() {}
diff --git a/src/test/run-pass/ctfe/const-block-non-item-statement.rs b/src/test/run-pass/ctfe/const-block-non-item-statement.rs
index 0943818e2b7..b7ed8af35d4 100644
--- a/src/test/run-pass/ctfe/const-block-non-item-statement.rs
+++ b/src/test/run-pass/ctfe/const-block-non-item-statement.rs
@@ -11,6 +11,8 @@
 // run-pass
 #![allow(dead_code)]
 
+#![feature(const_let)]
+
 enum Foo {
     Bar = { let x = 1; 3 }
 }
diff --git a/src/test/run-pass/ctfe/locals-in-const-fn.rs b/src/test/run-pass/ctfe/locals-in-const-fn.rs
index c4413dba69f..d10465b9dcd 100644
--- a/src/test/run-pass/ctfe/locals-in-const-fn.rs
+++ b/src/test/run-pass/ctfe/locals-in-const-fn.rs
@@ -12,7 +12,7 @@
 
 // https://github.com/rust-lang/rust/issues/48821
 
-#![feature(const_fn)]
+#![feature(const_fn, const_let)]
 
 const fn foo(i: usize) -> usize {
     let x = i;
diff --git a/src/test/ui/check-static-values-constraints.nll.stderr b/src/test/ui/check-static-values-constraints.nll.stderr
index ac549cd8d1a..5522e22fb1f 100644
--- a/src/test/ui/check-static-values-constraints.nll.stderr
+++ b/src/test/ui/check-static-values-constraints.nll.stderr
@@ -13,80 +13,44 @@ error[E0010]: allocations are not allowed in statics
 LL | static STATIC11: Box<MyOwned> = box MyOwned;
    |                                 ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:89:37
-   |
-LL | static STATIC11: Box<MyOwned> = box MyOwned;
-   |                                     ^^^^^^^
-
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/check-static-values-constraints.rs:100:32
+  --> $DIR/check-static-values-constraints.rs:99:32
    |
 LL |     field2: SafeEnum::Variant4("str".to_string())
    |                                ^^^^^^^^^^^^^^^^^
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:105:5
+  --> $DIR/check-static-values-constraints.rs:104:5
    |
 LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
    |     ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:105:9
-   |
-LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
-   |         ^^^^^^^
-
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:107:5
+  --> $DIR/check-static-values-constraints.rs:105:5
    |
 LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
    |     ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:107:9
-   |
-LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
-   |         ^^^^^^^
-
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:112:6
+  --> $DIR/check-static-values-constraints.rs:109:6
    |
 LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
    |      ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:112:10
-   |
-LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
-   |          ^^^^^^^
-
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:114:6
+  --> $DIR/check-static-values-constraints.rs:110:6
    |
 LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
    |      ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:114:10
-   |
-LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
-   |          ^^^^^^^
-
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:121:5
+  --> $DIR/check-static-values-constraints.rs:116:5
    |
 LL |     box 3;
    |     ^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:121:9
-   |
-LL |     box 3;
-   |         ^
-
 error[E0507]: cannot move out of static item
-  --> $DIR/check-static-values-constraints.rs:126:45
+  --> $DIR/check-static-values-constraints.rs:120:45
    |
 LL |     let y = { static x: Box<isize> = box 3; x };
    |                                             ^
@@ -95,18 +59,12 @@ LL |     let y = { static x: Box<isize> = box 3; x };
    |                                             help: consider borrowing here: `&x`
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:126:38
+  --> $DIR/check-static-values-constraints.rs:120:38
    |
 LL |     let y = { static x: Box<isize> = box 3; x };
    |                                      ^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:126:42
-   |
-LL |     let y = { static x: Box<isize> = box 3; x };
-   |                                          ^
-
-error: aborting due to 17 previous errors
+error: aborting due to 10 previous errors
 
-Some errors occurred: E0010, E0015, E0019, E0493, E0507.
+Some errors occurred: E0010, E0015, E0493, E0507.
 For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/check-static-values-constraints.rs b/src/test/ui/check-static-values-constraints.rs
index 1822af33323..37f665960c8 100644
--- a/src/test/ui/check-static-values-constraints.rs
+++ b/src/test/ui/check-static-values-constraints.rs
@@ -88,7 +88,6 @@ struct MyOwned;
 
 static STATIC11: Box<MyOwned> = box MyOwned;
 //~^ ERROR allocations are not allowed in statics
-//~| ERROR contains unimplemented expression type
 
 static mut STATIC12: UnsafeStruct = UnsafeStruct;
 
@@ -103,16 +102,12 @@ static mut STATIC14: SafeStruct = SafeStruct {
 
 static STATIC15: &'static [Box<MyOwned>] = &[
     box MyOwned, //~ ERROR allocations are not allowed in statics
-    //~^ ERROR contains unimplemented expression type
     box MyOwned, //~ ERROR allocations are not allowed in statics
-    //~^ ERROR contains unimplemented expression type
 ];
 
 static STATIC16: (&'static Box<MyOwned>, &'static Box<MyOwned>) = (
     &box MyOwned, //~ ERROR allocations are not allowed in statics
-    //~^ ERROR contains unimplemented expression type
     &box MyOwned, //~ ERROR allocations are not allowed in statics
-    //~^ ERROR contains unimplemented expression type
 );
 
 static mut STATIC17: SafeEnum = SafeEnum::Variant1;
@@ -120,11 +115,9 @@ static mut STATIC17: SafeEnum = SafeEnum::Variant1;
 static STATIC19: Box<isize> =
     box 3;
 //~^ ERROR allocations are not allowed in statics
-//~| ERROR contains unimplemented expression type
 
 pub fn main() {
     let y = { static x: Box<isize> = box 3; x };
     //~^ ERROR allocations are not allowed in statics
     //~^^ ERROR cannot move out of static item
-    //~| ERROR contains unimplemented expression type
 }
diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr
index 40f8555f6af..ac979a3fa7c 100644
--- a/src/test/ui/check-static-values-constraints.stderr
+++ b/src/test/ui/check-static-values-constraints.stderr
@@ -13,97 +13,55 @@ error[E0010]: allocations are not allowed in statics
 LL | static STATIC11: Box<MyOwned> = box MyOwned;
    |                                 ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:89:37
-   |
-LL | static STATIC11: Box<MyOwned> = box MyOwned;
-   |                                     ^^^^^^^
-
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/check-static-values-constraints.rs:100:32
+  --> $DIR/check-static-values-constraints.rs:99:32
    |
 LL |     field2: SafeEnum::Variant4("str".to_string())
    |                                ^^^^^^^^^^^^^^^^^
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:105:5
+  --> $DIR/check-static-values-constraints.rs:104:5
    |
 LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
    |     ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:105:9
-   |
-LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
-   |         ^^^^^^^
-
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:107:5
+  --> $DIR/check-static-values-constraints.rs:105:5
    |
 LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
    |     ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:107:9
-   |
-LL |     box MyOwned, //~ ERROR allocations are not allowed in statics
-   |         ^^^^^^^
-
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:112:6
+  --> $DIR/check-static-values-constraints.rs:109:6
    |
 LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
    |      ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:112:10
-   |
-LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
-   |          ^^^^^^^
-
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:114:6
+  --> $DIR/check-static-values-constraints.rs:110:6
    |
 LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
    |      ^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:114:10
-   |
-LL |     &box MyOwned, //~ ERROR allocations are not allowed in statics
-   |          ^^^^^^^
-
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:121:5
+  --> $DIR/check-static-values-constraints.rs:116:5
    |
 LL |     box 3;
    |     ^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:121:9
-   |
-LL |     box 3;
-   |         ^
-
 error[E0507]: cannot move out of static item
-  --> $DIR/check-static-values-constraints.rs:126:45
+  --> $DIR/check-static-values-constraints.rs:120:45
    |
 LL |     let y = { static x: Box<isize> = box 3; x };
    |                                             ^ cannot move out of static item
 
 error[E0010]: allocations are not allowed in statics
-  --> $DIR/check-static-values-constraints.rs:126:38
+  --> $DIR/check-static-values-constraints.rs:120:38
    |
 LL |     let y = { static x: Box<isize> = box 3; x };
    |                                      ^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/check-static-values-constraints.rs:126:42
-   |
-LL |     let y = { static x: Box<isize> = box 3; x };
-   |                                          ^
-
-error: aborting due to 17 previous errors
+error: aborting due to 10 previous errors
 
-Some errors occurred: E0010, E0015, E0019, E0493, E0507.
+Some errors occurred: E0010, E0015, E0493, E0507.
 For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/consts/const-block-non-item-statement-2.rs b/src/test/ui/consts/const-block-non-item-statement-2.rs
index 0e96f96e3d1..f80d55cb342 100644
--- a/src/test/ui/consts/const-block-non-item-statement-2.rs
+++ b/src/test/ui/consts/const-block-non-item-statement-2.rs
@@ -8,17 +8,21 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
-
 const A: usize = { 1; 2 };
+//~^ ERROR statements in constants are unstable
 
 const B: usize = { { } 2 };
+//~^ ERROR statements in constants are unstable
 
 macro_rules! foo {
-    () => (())
+    () => (()) //~ ERROR statements in constants are unstable
 }
 const C: usize = { foo!(); 2 };
 
 const D: usize = { let x = 4; 2 };
+//~^ ERROR let bindings in constants are unstable
+//~| ERROR statements in constants are unstable
+//~| ERROR let bindings in constants are unstable
+//~| ERROR statements in constants are unstable
 
 pub fn main() {}
diff --git a/src/test/ui/consts/const-block-non-item-statement-2.stderr b/src/test/ui/consts/const-block-non-item-statement-2.stderr
new file mode 100644
index 00000000000..580f7e039d1
--- /dev/null
+++ b/src/test/ui/consts/const-block-non-item-statement-2.stderr
@@ -0,0 +1,62 @@
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-2.rs:11:20
+   |
+LL | const A: usize = { 1; 2 };
+   |                    ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-2.rs:14:20
+   |
+LL | const B: usize = { { } 2 };
+   |                    ^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-2.rs:18:12
+   |
+LL |     () => (()) //~ ERROR statements in constants are unstable
+   |            ^^
+LL | }
+LL | const C: usize = { foo!(); 2 };
+   |                    ------- in this macro invocation
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-2.rs:22:28
+   |
+LL | const D: usize = { let x = 4; 2 };
+   |                            ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-2.rs:22:28
+   |
+LL | const D: usize = { let x = 4; 2 };
+   |                            ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-2.rs:22:1
+   |
+LL | const D: usize = { let x = 4; 2 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-2.rs:22:1
+   |
+LL | const D: usize = { let x = 4; 2 };
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 7 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-block-non-item-statement-3.rs b/src/test/ui/consts/const-block-non-item-statement-3.rs
index 496e5486e9b..cfa4b778dde 100644
--- a/src/test/ui/consts/const-block-non-item-statement-3.rs
+++ b/src/test/ui/consts/const-block-non-item-statement-3.rs
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
-
 type Array = [u32; {  let x = 2; 5 }];
+//~^ ERROR let bindings in constants are unstable
+//~| ERROR statements in constants are unstable
+//~| ERROR let bindings in constants are unstable
+//~| ERROR statements in constants are unstable
 
 pub fn main() {}
diff --git a/src/test/ui/consts/const-block-non-item-statement-3.stderr b/src/test/ui/consts/const-block-non-item-statement-3.stderr
new file mode 100644
index 00000000000..0124288d43d
--- /dev/null
+++ b/src/test/ui/consts/const-block-non-item-statement-3.stderr
@@ -0,0 +1,35 @@
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-3.rs:11:31
+   |
+LL | type Array = [u32; {  let x = 2; 5 }];
+   |                               ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-3.rs:11:31
+   |
+LL | type Array = [u32; {  let x = 2; 5 }];
+   |                               ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-3.rs:11:20
+   |
+LL | type Array = [u32; {  let x = 2; 5 }];
+   |                    ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement-3.rs:11:20
+   |
+LL | type Array = [u32; {  let x = 2; 5 }];
+   |                    ^^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-block-non-item-statement.rs b/src/test/ui/consts/const-block-non-item-statement.rs
index 281a07808e9..f974a24c26f 100644
--- a/src/test/ui/consts/const-block-non-item-statement.rs
+++ b/src/test/ui/consts/const-block-non-item-statement.rs
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
-
 enum Foo {
     Bar = { let x = 1; 3 }
+    //~^ ERROR let bindings in constants are unstable
+    //~| ERROR statements in constants are unstable
+    //~| ERROR let bindings in constants are unstable
+    //~| ERROR statements in constants are unstable
 }
 
 pub fn main() {}
diff --git a/src/test/ui/consts/const-block-non-item-statement.stderr b/src/test/ui/consts/const-block-non-item-statement.stderr
new file mode 100644
index 00000000000..b367a9d9937
--- /dev/null
+++ b/src/test/ui/consts/const-block-non-item-statement.stderr
@@ -0,0 +1,35 @@
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement.rs:12:21
+   |
+LL |     Bar = { let x = 1; 3 }
+   |                     ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement.rs:12:21
+   |
+LL |     Bar = { let x = 1; 3 }
+   |                     ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement.rs:12:11
+   |
+LL |     Bar = { let x = 1; 3 }
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/const-block-non-item-statement.rs:12:11
+   |
+LL |     Bar = { let x = 1; 3 }
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
index ad0dfabebed..63e5bcccf5d 100644
--- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.rs
@@ -12,6 +12,7 @@
 // The test should never compile successfully
 
 #![feature(const_raw_ptr_deref)]
+#![feature(const_let)]
 
 use std::cell::UnsafeCell;
 
@@ -23,7 +24,7 @@ unsafe impl Sync for Foo {}
 static FOO: Foo = Foo(UnsafeCell::new(42));
 
 static BAR: () = unsafe {
-    *FOO.0.get() = 5; //~ ERROR static contains unimplemented expression type
+    *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
 };
 
 fn main() {}
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
index 740c1ab0b2d..740954c6c66 100644
--- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static-2.stderr
@@ -1,7 +1,7 @@
 error[E0019]: static contains unimplemented expression type
-  --> $DIR/assign-to-static-within-other-static-2.rs:26:5
+  --> $DIR/assign-to-static-within-other-static-2.rs:27:5
    |
-LL |     *FOO.0.get() = 5; //~ ERROR static contains unimplemented expression type
+LL |     *FOO.0.get() = 5; //~ ERROR contains unimplemented expression type
    |     ^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs
index 2f786fb16cc..6f16f644eec 100644
--- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.rs
@@ -12,6 +12,7 @@
 // The test should never compile successfully
 
 #![feature(const_raw_ptr_deref)]
+#![feature(const_let)]
 
 use std::cell::UnsafeCell;
 
diff --git a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr
index 031a8770126..ca652c9df32 100644
--- a/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr
+++ b/src/test/ui/consts/const-eval/assign-to-static-within-other-static.stderr
@@ -1,5 +1,5 @@
 error: cannot mutate statics in the initializer of another static
-  --> $DIR/assign-to-static-within-other-static.rs:20:5
+  --> $DIR/assign-to-static-within-other-static.rs:21:5
    |
 LL |     FOO = 5; //~ ERROR cannot mutate statics in the initializer of another static
    |     ^^^^^^^
diff --git a/src/test/ui/consts/const-eval/const_let.rs b/src/test/ui/consts/const-eval/const_let.rs
index 3b5014a57b5..602d4da24f3 100644
--- a/src/test/ui/consts/const-eval/const_let.rs
+++ b/src/test/ui/consts/const-eval/const_let.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(const_let)]
+
 fn main() {}
 
 struct FakeNeedsDrop;
diff --git a/src/test/ui/consts/const-eval/const_let.stderr b/src/test/ui/consts/const-eval/const_let.stderr
index f0c17bca36a..86e3482fda6 100644
--- a/src/test/ui/consts/const-eval/const_let.stderr
+++ b/src/test/ui/consts/const-eval/const_let.stderr
@@ -1,11 +1,11 @@
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/const_let.rs:23:55
+  --> $DIR/const_let.rs:25:55
    |
 LL | const Y: FakeNeedsDrop = { let mut x = FakeNeedsDrop; x = FakeNeedsDrop; x };
    |                                                       ^
 
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/const_let.rs:27:35
+  --> $DIR/const_let.rs:29:35
    |
 LL | const Z: () = { let mut x = None; x = Some(FakeNeedsDrop); };
    |                                   ^
diff --git a/src/test/ui/consts/const-eval/infinite_loop.rs b/src/test/ui/consts/const-eval/infinite_loop.rs
index 4aad5216442..d23b6250b4d 100644
--- a/src/test/ui/consts/const-eval/infinite_loop.rs
+++ b/src/test/ui/consts/const-eval/infinite_loop.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(const_let)]
+
 fn main() {
     // Tests the Collatz conjecture with an incorrect base case (0 instead of 1).
     // The value of `n` will loop indefinitely (4 - 2 - 1 - 4).
diff --git a/src/test/ui/consts/const-eval/infinite_loop.stderr b/src/test/ui/consts/const-eval/infinite_loop.stderr
index 04a3362d95e..2ff80e5efb5 100644
--- a/src/test/ui/consts/const-eval/infinite_loop.stderr
+++ b/src/test/ui/consts/const-eval/infinite_loop.stderr
@@ -1,5 +1,5 @@
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/infinite_loop.rs:17:9
+  --> $DIR/infinite_loop.rs:19:9
    |
 LL | /         while n != 0 { //~ ERROR constant contains unimplemented expression type
 LL | |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
@@ -8,7 +8,7 @@ LL | |         }
    | |_________^
 
 warning: Constant evaluating a complex constant, this might take some time
-  --> $DIR/infinite_loop.rs:14:18
+  --> $DIR/infinite_loop.rs:16:18
    |
 LL |       let _ = [(); {
    |  __________________^
@@ -21,7 +21,7 @@ LL | |     }];
    | |_____^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/infinite_loop.rs:18:20
+  --> $DIR/infinite_loop.rs:20:20
    |
 LL |             n = if n % 2 == 0 { n/2 } else { 3*n + 1 };
    |                    ^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
diff --git a/src/test/ui/consts/const-eval/issue-52475.rs b/src/test/ui/consts/const-eval/issue-52475.rs
index 970d1a056f3..b21c1827e2b 100644
--- a/src/test/ui/consts/const-eval/issue-52475.rs
+++ b/src/test/ui/consts/const-eval/issue-52475.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(const_let)]
+
 fn main() {
     let _ = [(); {
         //~^ WARNING Constant evaluating a complex constant, this might take some time
diff --git a/src/test/ui/consts/const-eval/issue-52475.stderr b/src/test/ui/consts/const-eval/issue-52475.stderr
index 128979a67a9..c0cd98b2fca 100644
--- a/src/test/ui/consts/const-eval/issue-52475.stderr
+++ b/src/test/ui/consts/const-eval/issue-52475.stderr
@@ -1,5 +1,5 @@
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/issue-52475.rs:16:9
+  --> $DIR/issue-52475.rs:18:9
    |
 LL | /         while n < 5 { //~ ERROR constant contains unimplemented expression type
 LL | |             n = (n + 1) % 5; //~ ERROR evaluation of constant value failed
@@ -8,7 +8,7 @@ LL | |         }
    | |_________^
 
 warning: Constant evaluating a complex constant, this might take some time
-  --> $DIR/issue-52475.rs:12:18
+  --> $DIR/issue-52475.rs:14:18
    |
 LL |       let _ = [(); {
    |  __________________^
@@ -21,7 +21,7 @@ LL | |     }];
    | |_____^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/issue-52475.rs:17:17
+  --> $DIR/issue-52475.rs:19:17
    |
 LL |             n = (n + 1) % 5; //~ ERROR evaluation of constant value failed
    |                 ^^^^^^^^^^^ duplicate interpreter state observed here, const evaluation will never terminate
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
index 8132d26d63b..6c2fdcc8615 100644
--- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.rs
@@ -12,6 +12,7 @@
 // The test should never compile successfully
 
 #![feature(const_raw_ptr_deref)]
+#![feature(const_let)]
 
 use std::cell::UnsafeCell;
 
@@ -26,7 +27,7 @@ fn foo() {}
 
 static BAR: () = unsafe {
     *FOO.0.get() = 5;
-    //~^ ERROR static contains unimplemented expression
+    //~^ contains unimplemented expression
 
     foo();
     //~^ ERROR calls in statics are limited to constant functions, tuple structs and tuple variants
diff --git a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
index eb5e88ad693..49b39e2f5c6 100644
--- a/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
+++ b/src/test/ui/consts/const-eval/mod-static-with-const-fn.stderr
@@ -1,11 +1,11 @@
 error[E0019]: static contains unimplemented expression type
-  --> $DIR/mod-static-with-const-fn.rs:28:5
+  --> $DIR/mod-static-with-const-fn.rs:29:5
    |
 LL |     *FOO.0.get() = 5;
    |     ^^^^^^^^^^^^^^^^
 
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/mod-static-with-const-fn.rs:31:5
+  --> $DIR/mod-static-with-const-fn.rs:32:5
    |
 LL |     foo();
    |     ^^^^^
diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr
index 20e6593f88a..7141d7ac8b8 100644
--- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr
+++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr
@@ -21,6 +21,17 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_raw_ptr_ops.rs:17:28
+   |
+LL |     let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
+   |            ------------    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |     let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does not live long enough
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error[E0716]: temporary value dropped while borrowed
   --> $DIR/promoted_raw_ptr_ops.rs:18:29
    |
 LL |     let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does not live long enough
@@ -30,6 +41,6 @@ LL |     let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does
 LL | }
    | - temporary value is freed at the end of this statement
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/ub-upvars.rs b/src/test/ui/consts/const-eval/ub-upvars.rs
index a9d5d690152..6661de4ab2c 100644
--- a/src/test/ui/consts/const-eval/ub-upvars.rs
+++ b/src/test/ui/consts/const-eval/ub-upvars.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(const_transmute)]
+#![feature(const_transmute,const_let)]
 #![allow(const_err)] // make sure we cannot allow away the errors tested here
 
 use std::mem;
diff --git a/src/test/ui/consts/const-fn-destructuring-arg.rs b/src/test/ui/consts/const-fn-destructuring-arg.rs
index 8aa6871fa75..fce1688716d 100644
--- a/src/test/ui/consts/const-fn-destructuring-arg.rs
+++ b/src/test/ui/consts/const-fn-destructuring-arg.rs
@@ -8,10 +8,20 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-pass
+// test that certain things are disallowed in constant functions
 
-const fn i((a, b): (u32, u32)) -> u32 {
+#![feature(const_fn)]
+
+// no destructuring
+const fn i((
+            a,
+            //~^ ERROR arguments of constant functions can only be immutable by-value bindings
+            b
+            //~^ ERROR arguments of constant functions can only be immutable by-value bindings
+           ): (u32, u32)) -> u32 {
     a + b
+    //~^ ERROR let bindings in constant functions are unstable
+    //~| ERROR let bindings in constant functions are unstable
 }
 
 fn main() {}
diff --git a/src/test/ui/consts/const-fn-destructuring-arg.stderr b/src/test/ui/consts/const-fn-destructuring-arg.stderr
new file mode 100644
index 00000000000..029d63a7720
--- /dev/null
+++ b/src/test/ui/consts/const-fn-destructuring-arg.stderr
@@ -0,0 +1,35 @@
+error[E0658]: arguments of constant functions can only be immutable by-value bindings (see issue #48821)
+  --> $DIR/const-fn-destructuring-arg.rs:17:13
+   |
+LL |             a,
+   |             ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: arguments of constant functions can only be immutable by-value bindings (see issue #48821)
+  --> $DIR/const-fn-destructuring-arg.rs:19:13
+   |
+LL |             b
+   |             ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+  --> $DIR/const-fn-destructuring-arg.rs:22:5
+   |
+LL |     a + b
+   |     ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+  --> $DIR/const-fn-destructuring-arg.rs:22:9
+   |
+LL |     a + b
+   |         ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.rs b/src/test/ui/consts/const-fn-not-safe-for-const.rs
index aee5539980c..2f7e2ecaa4e 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.rs
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.rs
@@ -37,9 +37,13 @@ const fn get_Y_addr() -> &'static u32 {
 }
 
 const fn get() -> u32 {
-    let x = 22;
-    let y = 44;
+    let x = 22; //~ ERROR let bindings in constant functions are unstable
+//~^ ERROR statements in constant functions
+    let y = 44; //~ ERROR let bindings in constant functions are unstable
+//~^ ERROR statements in constant functions
     x + y
+//~^ ERROR let bindings in constant functions are unstable
+//~| ERROR let bindings in constant functions are unstable
 }
 
 fn main() {}
diff --git a/src/test/ui/consts/const-fn-not-safe-for-const.stderr b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
index 90a7314b7d1..1a8c5f558a2 100644
--- a/src/test/ui/consts/const-fn-not-safe-for-const.stderr
+++ b/src/test/ui/consts/const-fn-not-safe-for-const.stderr
@@ -16,7 +16,55 @@ error[E0013]: constant functions cannot refer to statics, use a constant instead
 LL |     &Y
    |     ^^
 
-error: aborting due to 3 previous errors
+error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+  --> $DIR/const-fn-not-safe-for-const.rs:40:13
+   |
+LL |     let x = 22; //~ ERROR let bindings in constant functions are unstable
+   |             ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constant functions are unstable (see issue #48821)
+  --> $DIR/const-fn-not-safe-for-const.rs:40:13
+   |
+LL |     let x = 22; //~ ERROR let bindings in constant functions are unstable
+   |             ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+  --> $DIR/const-fn-not-safe-for-const.rs:42:13
+   |
+LL |     let y = 44; //~ ERROR let bindings in constant functions are unstable
+   |             ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constant functions are unstable (see issue #48821)
+  --> $DIR/const-fn-not-safe-for-const.rs:42:13
+   |
+LL |     let y = 44; //~ ERROR let bindings in constant functions are unstable
+   |             ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+  --> $DIR/const-fn-not-safe-for-const.rs:44:5
+   |
+LL |     x + y
+   |     ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constant functions are unstable (see issue #48821)
+  --> $DIR/const-fn-not-safe-for-const.rs:44:9
+   |
+LL |     x + y
+   |         ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 9 previous errors
 
-Some errors occurred: E0013, E0015.
+Some errors occurred: E0013, E0015, E0658.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/src/test/ui/consts/const_let_assign.rs b/src/test/ui/consts/const_let_assign.rs
index 0b09b8469fd..a3c53a451e1 100644
--- a/src/test/ui/consts/const_let_assign.rs
+++ b/src/test/ui/consts/const_let_assign.rs
@@ -1,5 +1,7 @@
 // compile-pass
 
+#![feature(const_let)]
+
 struct S(i32);
 
 const A: () = {
diff --git a/src/test/ui/consts/const_let_assign2.rs b/src/test/ui/consts/const_let_assign2.rs
index 1c44237e49b..0de7396501a 100644
--- a/src/test/ui/consts/const_let_assign2.rs
+++ b/src/test/ui/consts/const_let_assign2.rs
@@ -1,5 +1,8 @@
 // compile-pass
 
+#![feature(const_let)]
+#![feature(const_fn)]
+
 pub struct AA {
     pub data: [u8; 10],
 }
diff --git a/src/test/ui/consts/const_let_assign3.rs b/src/test/ui/consts/const_let_assign3.rs
index dd9690ef858..c2ed6cd85ab 100644
--- a/src/test/ui/consts/const_let_assign3.rs
+++ b/src/test/ui/consts/const_let_assign3.rs
@@ -1,3 +1,4 @@
+#![feature(const_let)]
 #![feature(const_fn)]
 
 struct S {
@@ -7,7 +8,7 @@ struct S {
 impl S {
     const fn foo(&mut self, x: u32) {
         self.state = x;
-        //~^ ERROR constant function contains unimplemented expression
+        //~^ contains unimplemented expression
     }
 }
 
diff --git a/src/test/ui/consts/const_let_assign3.stderr b/src/test/ui/consts/const_let_assign3.stderr
index 7380906bec7..0f294616d25 100644
--- a/src/test/ui/consts/const_let_assign3.stderr
+++ b/src/test/ui/consts/const_let_assign3.stderr
@@ -1,11 +1,11 @@
 error[E0019]: constant function contains unimplemented expression type
-  --> $DIR/const_let_assign3.rs:9:9
+  --> $DIR/const_let_assign3.rs:10:9
    |
 LL |         self.state = x;
    |         ^^^^^^^^^^^^^^
 
 error[E0017]: references in constants may only refer to immutable values
-  --> $DIR/const_let_assign3.rs:16:5
+  --> $DIR/const_let_assign3.rs:17:5
    |
 LL |     s.foo(3); //~ ERROR references in constants may only refer to immutable values
    |     ^ constants require immutable values
diff --git a/src/test/ui/consts/const_let_eq.rs b/src/test/ui/consts/const_let_eq.rs
index a2364c392f2..8739cb80e94 100644
--- a/src/test/ui/consts/const_let_eq.rs
+++ b/src/test/ui/consts/const_let_eq.rs
@@ -1,3 +1,5 @@
+#![feature(const_let, const_fn)]
+
 // run-pass
 
 struct Foo<T>(T);
diff --git a/src/test/ui/consts/const_short_circuit.rs b/src/test/ui/consts/const_short_circuit.rs
index 9721c1969d5..e644886b923 100644
--- a/src/test/ui/consts/const_short_circuit.rs
+++ b/src/test/ui/consts/const_short_circuit.rs
@@ -1,4 +1,4 @@
-#![feature(underscore_const_names)]
+#![feature(underscore_const_names, const_let)]
 
 const _: bool = false && false; //~ WARN boolean short circuiting operators in constants
 const _: bool = true && false; //~ WARN boolean short circuiting operators in constants
@@ -13,4 +13,4 @@ const _: bool = {
     x
 };
 
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs
index dbc50f1fbd4..695d33b6908 100644
--- a/src/test/ui/consts/dangling-alloc-id-ice.rs
+++ b/src/test/ui/consts/dangling-alloc-id-ice.rs
@@ -1,5 +1,7 @@
 // https://github.com/rust-lang/rust/issues/55223
 
+#![feature(const_let)]
+
 union Foo<'a> {
     y: &'a (),
     long_live_the_unit: &'static (),
diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr
index 2cd8711f03d..a5fa88e5e68 100644
--- a/src/test/ui/consts/dangling-alloc-id-ice.stderr
+++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr
@@ -1,5 +1,5 @@
 error: any use of this value will cause an error
-  --> $DIR/dangling-alloc-id-ice.rs:8:1
+  --> $DIR/dangling-alloc-id-ice.rs:10:1
    |
 LL | / const FOO: &() = { //~ ERROR any use of this value will cause an error
 LL | |     let y = ();
diff --git a/src/test/ui/consts/dangling_raw_ptr.rs b/src/test/ui/consts/dangling_raw_ptr.rs
index c2d8e6d421a..7fc773412f2 100644
--- a/src/test/ui/consts/dangling_raw_ptr.rs
+++ b/src/test/ui/consts/dangling_raw_ptr.rs
@@ -1,3 +1,5 @@
+#![feature(const_let)]
+
 const FOO: *const u32 = { //~ ERROR any use of this value will cause an error
     let x = 42;
     &x
diff --git a/src/test/ui/consts/dangling_raw_ptr.stderr b/src/test/ui/consts/dangling_raw_ptr.stderr
index 091f1f785cb..3b20936f8ae 100644
--- a/src/test/ui/consts/dangling_raw_ptr.stderr
+++ b/src/test/ui/consts/dangling_raw_ptr.stderr
@@ -1,5 +1,5 @@
 error: any use of this value will cause an error
-  --> $DIR/dangling_raw_ptr.rs:1:1
+  --> $DIR/dangling_raw_ptr.rs:3:1
    |
 LL | / const FOO: *const u32 = { //~ ERROR any use of this value will cause an error
 LL | |     let x = 42;
diff --git a/src/test/ui/consts/issue-54224.rs b/src/test/ui/consts/issue-54224.rs
index bb6be37340c..b5a8fe8819c 100644
--- a/src/test/ui/consts/issue-54224.rs
+++ b/src/test/ui/consts/issue-54224.rs
@@ -1,8 +1,6 @@
-// compile-pass
-
 #![feature(nll)]
 
-const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]);
+const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); //~ ERROR temporary value dropped while borrowed
 
 use std::borrow::Cow;
 
@@ -11,5 +9,6 @@ pub const Y: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[X]);
 
 
 pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]);
+//~^ ERROR temporary value dropped while borrowed
 
 fn main() {}
diff --git a/src/test/ui/consts/issue-54224.stderr b/src/test/ui/consts/issue-54224.stderr
new file mode 100644
index 00000000000..451f49c1cb5
--- /dev/null
+++ b/src/test/ui/consts/issue-54224.stderr
@@ -0,0 +1,23 @@
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-54224.rs:3:39
+   |
+LL | const FOO: Option<&[[u8; 3]]> = Some(&[*b"foo"]); //~ ERROR temporary value dropped while borrowed
+   |                                 ------^^^^^^^^^-
+   |                                 |     |        |
+   |                                 |     |        temporary value is freed at the end of this statement
+   |                                 |     creates a temporary which is freed while still in use
+   |                                 using this value as a constant requires that borrow lasts for `'static`
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/issue-54224.rs:11:57
+   |
+LL | pub const Z: Cow<'static, [ [u8; 3] ]> = Cow::Borrowed(&[*b"ABC"]);
+   |                                          ---------------^^^^^^^^^-
+   |                                          |              |        |
+   |                                          |              |        temporary value is freed at the end of this statement
+   |                                          |              creates a temporary which is freed while still in use
+   |                                          using this value as a constant requires that borrow lasts for `'static`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
index 39adf088642..6c4e9e0a067 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.nll.stderr
@@ -112,6 +112,12 @@ error: `if`, `match`, `&&` and `||` are not stable in const fn
 LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
    |                             ^^^^^^^^^^^
 
+error: local variables in const fn are unstable
+  --> $DIR/min_const_fn.rs:109:34
+   |
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
+   |                                  ^
+
 error: `if`, `match`, `&&` and `||` are not stable in const fn
   --> $DIR/min_const_fn.rs:110:44
    |
@@ -215,7 +221,7 @@ error: function pointers in const fn are unstable
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
 
-error: aborting due to 34 previous errors
+error: aborting due to 35 previous errors
 
 Some errors occurred: E0493, E0515.
 For more information about an error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs
index 80db24006ec..ba6989f8b41 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.rs
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs
@@ -106,7 +106,7 @@ const fn foo30_2(x: *mut u32) -> usize { x as usize }
 const fn foo30_4(b: bool) -> usize { if b { 1 } else { 42 } }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
-const fn foo30_6() -> bool { let x = true; x }
+const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
 const fn foo36(a: bool, b: bool) -> bool { a && b }
 //~^ ERROR `if`, `match`, `&&` and `||` are not stable in const fn
 const fn foo37(a: bool, b: bool) -> bool { a || b }
diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
index 530282cfea9..a93a4f817fc 100644
--- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr
+++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr
@@ -112,6 +112,12 @@ error: `if`, `match`, `&&` and `||` are not stable in const fn
 LL | const fn foo30_5(b: bool) { while b { } } //~ ERROR not stable in const fn
    |                             ^^^^^^^^^^^
 
+error: local variables in const fn are unstable
+  --> $DIR/min_const_fn.rs:109:34
+   |
+LL | const fn foo30_6() -> bool { let x = true; x } //~ ERROR local variables in const fn
+   |                                  ^
+
 error: `if`, `match`, `&&` and `||` are not stable in const fn
   --> $DIR/min_const_fn.rs:110:44
    |
@@ -202,6 +208,6 @@ error: function pointers in const fn are unstable
 LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo }
    |                           ^^^^
 
-error: aborting due to 34 previous errors
+error: aborting due to 35 previous errors
 
 For more information about this error, try `rustc --explain E0493`.
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.nll.stderr b/src/test/ui/consts/min_const_fn/mutable_borrow.nll.stderr
deleted file mode 100644
index 7a0cd939c14..00000000000
--- a/src/test/ui/consts/min_const_fn/mutable_borrow.nll.stderr
+++ /dev/null
@@ -1,51 +0,0 @@
-error: mutable references in const fn are unstable
-  --> $DIR/mutable_borrow.rs:3:9
-   |
-LL |     let b = &mut a; //~ ERROR mutable references in const fn are unstable
-   |         ^
-
-error: mutable references in const fn are unstable
-  --> $DIR/mutable_borrow.rs:12:13
-   |
-LL |         let b = &mut a; //~ ERROR mutable references in const fn are unstable
-   |             ^
-
-error[E0017]: references in statics may only refer to immutable values
-  --> $DIR/mutable_borrow.rs:19:13
-   |
-LL |     let b = &mut a; //~ references in statics may only refer to immutable
-   |             ^^^^^^ statics require immutable values
-
-error[E0017]: references in statics may only refer to immutable values
-  --> $DIR/mutable_borrow.rs:26:15
-   |
-LL |     { let b = &mut a; }  //~ references in statics may only refer to immutable
-   |               ^^^^^^ statics require immutable values
-
-error[E0017]: references in statics may only refer to immutable values
-  --> $DIR/mutable_borrow.rs:37:17
-   |
-LL |     let mut a = &mut None; //~ references in statics may only refer to immutable values
-   |                 ^^^^^^^^^ statics require immutable values
-
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/mutable_borrow.rs:39:5
-   |
-LL |     *a = Some(Foo); //~ unimplemented expression type
-   |     ^^
-
-error[E0716]: temporary value dropped while borrowed
-  --> $DIR/mutable_borrow.rs:37:22
-   |
-LL |     let mut a = &mut None; //~ references in statics may only refer to immutable values
-   |                      ^^^^ creates a temporary which is freed while still in use
-...
-LL |     a
-   |     - using this value as a static requires that borrow lasts for `'static`
-LL | };
-   | - temporary value is freed at the end of this statement
-
-error: aborting due to 7 previous errors
-
-Some errors occurred: E0017, E0019, E0716.
-For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.rs b/src/test/ui/consts/min_const_fn/mutable_borrow.rs
index d9a4164aa13..3dd76b630a8 100644
--- a/src/test/ui/consts/min_const_fn/mutable_borrow.rs
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.rs
@@ -1,6 +1,6 @@
 const fn mutable_ref_in_const() -> u8 {
-    let mut a = 0;
-    let b = &mut a; //~ ERROR mutable references in const fn are unstable
+    let mut a = 0; //~ ERROR local variables in const fn
+    let b = &mut a;
     *b
 }
 
@@ -8,36 +8,10 @@ struct X;
 
 impl X {
     const fn inherent_mutable_ref_in_const() -> u8 {
-        let mut a = 0;
-        let b = &mut a; //~ ERROR mutable references in const fn are unstable
+        let mut a = 0; //~ ERROR local variables in const fn
+        let b = &mut a;
         *b
     }
 }
 
-static mut FOO: u32 = {
-    let mut a = 0;
-    let b = &mut a; //~ references in statics may only refer to immutable
-    *b
-};
-
-static mut BAR: Option<String> = {
-    let mut a = None;
-    // taking a mutable reference erases everything we know about `a`
-    { let b = &mut a; }  //~ references in statics may only refer to immutable
-    a
-};
-
-struct Foo;
-
-impl Drop for Foo {
-    fn drop(&mut self) {}
-}
-
-static mut BAR2: &mut Option<Foo> = {
-    let mut a = &mut None; //~ references in statics may only refer to immutable values
-    //~^ does not live long enough
-    *a = Some(Foo); //~ unimplemented expression type
-    a
-};
-
 fn main() {}
diff --git a/src/test/ui/consts/min_const_fn/mutable_borrow.stderr b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
index ac619490197..fa46f5c804f 100644
--- a/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
+++ b/src/test/ui/consts/min_const_fn/mutable_borrow.stderr
@@ -1,51 +1,14 @@
-error: mutable references in const fn are unstable
-  --> $DIR/mutable_borrow.rs:3:9
+error: local variables in const fn are unstable
+  --> $DIR/mutable_borrow.rs:2:9
    |
-LL |     let b = &mut a; //~ ERROR mutable references in const fn are unstable
-   |         ^
+LL |     let mut a = 0; //~ ERROR local variables in const fn
+   |         ^^^^^
 
-error: mutable references in const fn are unstable
-  --> $DIR/mutable_borrow.rs:12:13
+error: local variables in const fn are unstable
+  --> $DIR/mutable_borrow.rs:11:13
    |
-LL |         let b = &mut a; //~ ERROR mutable references in const fn are unstable
-   |             ^
+LL |         let mut a = 0; //~ ERROR local variables in const fn
+   |             ^^^^^
 
-error[E0017]: references in statics may only refer to immutable values
-  --> $DIR/mutable_borrow.rs:19:13
-   |
-LL |     let b = &mut a; //~ references in statics may only refer to immutable
-   |             ^^^^^^ statics require immutable values
-
-error[E0017]: references in statics may only refer to immutable values
-  --> $DIR/mutable_borrow.rs:26:15
-   |
-LL |     { let b = &mut a; }  //~ references in statics may only refer to immutable
-   |               ^^^^^^ statics require immutable values
-
-error[E0017]: references in statics may only refer to immutable values
-  --> $DIR/mutable_borrow.rs:37:17
-   |
-LL |     let mut a = &mut None; //~ references in statics may only refer to immutable values
-   |                 ^^^^^^^^^ statics require immutable values
-
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/mutable_borrow.rs:39:5
-   |
-LL |     *a = Some(Foo); //~ unimplemented expression type
-   |     ^^
-
-error[E0597]: borrowed value does not live long enough
-  --> $DIR/mutable_borrow.rs:37:22
-   |
-LL |     let mut a = &mut None; //~ references in statics may only refer to immutable values
-   |                      ^^^^ temporary value does not live long enough
-...
-LL | };
-   | - temporary value only lives until here
-   |
-   = note: borrowed value must be valid for the static lifetime...
-
-error: aborting due to 7 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0017, E0019, E0597.
-For more information about an error, try `rustc --explain E0017`.
diff --git a/src/test/ui/consts/partial_qualif.rs b/src/test/ui/consts/partial_qualif.rs
index 32c68e69f4b..4ce41f80f82 100644
--- a/src/test/ui/consts/partial_qualif.rs
+++ b/src/test/ui/consts/partial_qualif.rs
@@ -1,3 +1,5 @@
+#![feature(const_let)]
+
 use std::cell::Cell;
 
 const FOO: &(Cell<usize>, bool) = {
diff --git a/src/test/ui/consts/partial_qualif.stderr b/src/test/ui/consts/partial_qualif.stderr
index 967fb83b78b..d695f64e2c3 100644
--- a/src/test/ui/consts/partial_qualif.stderr
+++ b/src/test/ui/consts/partial_qualif.stderr
@@ -1,5 +1,5 @@
 error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/partial_qualif.rs:6:5
+  --> $DIR/partial_qualif.rs:8:5
    |
 LL |     &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
    |     ^^^^
diff --git a/src/test/ui/consts/projection_qualif.rs b/src/test/ui/consts/projection_qualif.rs
index 411cdff3d24..5863429a2f2 100644
--- a/src/test/ui/consts/projection_qualif.rs
+++ b/src/test/ui/consts/projection_qualif.rs
@@ -1,3 +1,5 @@
+#![feature(const_let)]
+
 use std::cell::Cell;
 
 const FOO: &u32 = {
@@ -5,7 +7,7 @@ const FOO: &u32 = {
     {
         let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
-        //~^ ERROR constant contains unimplemented expression
+        //~^ contains unimplemented expression
     }
     &{a}
 };
diff --git a/src/test/ui/consts/projection_qualif.stderr b/src/test/ui/consts/projection_qualif.stderr
index 410c51c4b54..cc3635a979b 100644
--- a/src/test/ui/consts/projection_qualif.stderr
+++ b/src/test/ui/consts/projection_qualif.stderr
@@ -1,17 +1,17 @@
 error[E0017]: references in constants may only refer to immutable values
-  --> $DIR/projection_qualif.rs:6:27
+  --> $DIR/projection_qualif.rs:8:27
    |
 LL |         let b: *mut u32 = &mut a; //~ ERROR may only refer to immutable values
    |                           ^^^^^^ constants require immutable values
 
 error[E0019]: constant contains unimplemented expression type
-  --> $DIR/projection_qualif.rs:7:18
+  --> $DIR/projection_qualif.rs:9:18
    |
 LL |         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
    |                  ^^^^^^
 
 error[E0658]: dereferencing raw pointers in constants is unstable (see issue #51911)
-  --> $DIR/projection_qualif.rs:7:18
+  --> $DIR/projection_qualif.rs:9:18
    |
 LL |         unsafe { *b = 5; } //~ ERROR dereferencing raw pointers in constants
    |                  ^^^^^^
diff --git a/src/test/ui/consts/promote_const_let.nll.stderr b/src/test/ui/consts/promote_const_let.nll.stderr
index 1fc345d5a12..d8749bb5fd9 100644
--- a/src/test/ui/consts/promote_const_let.nll.stderr
+++ b/src/test/ui/consts/promote_const_let.nll.stderr
@@ -1,5 +1,5 @@
 error[E0597]: `y` does not live long enough
-  --> $DIR/promote_const_let.rs:4:9
+  --> $DIR/promote_const_let.rs:6:9
    |
 LL |     let x: &'static u32 = {
    |            ------------ type annotation requires that `y` is borrowed for `'static`
diff --git a/src/test/ui/consts/promote_const_let.rs b/src/test/ui/consts/promote_const_let.rs
index cbebe84d905..8de9b00eb11 100644
--- a/src/test/ui/consts/promote_const_let.rs
+++ b/src/test/ui/consts/promote_const_let.rs
@@ -1,3 +1,5 @@
+#![feature(const_let)]
+
 fn main() {
     let x: &'static u32 = {
         let y = 42;
diff --git a/src/test/ui/consts/promote_const_let.stderr b/src/test/ui/consts/promote_const_let.stderr
index 2ec4ad90855..6bbb7495fb0 100644
--- a/src/test/ui/consts/promote_const_let.stderr
+++ b/src/test/ui/consts/promote_const_let.stderr
@@ -1,5 +1,5 @@
 error[E0597]: `y` does not live long enough
-  --> $DIR/promote_const_let.rs:4:10
+  --> $DIR/promote_const_let.rs:6:10
    |
 LL |         &y //~ ERROR does not live long enough
    |          ^ borrowed value does not live long enough
diff --git a/src/test/ui/consts/qualif_overwrite.rs b/src/test/ui/consts/qualif_overwrite.rs
index 430eea37de7..806a74ee453 100644
--- a/src/test/ui/consts/qualif_overwrite.rs
+++ b/src/test/ui/consts/qualif_overwrite.rs
@@ -1,3 +1,5 @@
+#![feature(const_let)]
+
 use std::cell::Cell;
 
 // this is overly conservative. The reset to `None` should clear `a` of all qualifications
diff --git a/src/test/ui/consts/qualif_overwrite.stderr b/src/test/ui/consts/qualif_overwrite.stderr
index 30479139e31..4fac64bf806 100644
--- a/src/test/ui/consts/qualif_overwrite.stderr
+++ b/src/test/ui/consts/qualif_overwrite.stderr
@@ -1,5 +1,5 @@
 error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/qualif_overwrite.rs:10:5
+  --> $DIR/qualif_overwrite.rs:12:5
    |
 LL |     &{a} //~ ERROR cannot borrow a constant which may contain interior mutability
    |     ^^^^
diff --git a/src/test/ui/consts/qualif_overwrite_2.rs b/src/test/ui/consts/qualif_overwrite_2.rs
index fa79b5c14a7..29557a3da47 100644
--- a/src/test/ui/consts/qualif_overwrite_2.rs
+++ b/src/test/ui/consts/qualif_overwrite_2.rs
@@ -1,3 +1,5 @@
+#![feature(const_let)]
+
 use std::cell::Cell;
 
 // const qualification is not smart enough to know about fields and always assumes that there might
diff --git a/src/test/ui/consts/qualif_overwrite_2.stderr b/src/test/ui/consts/qualif_overwrite_2.stderr
index 8276db99a12..181b728c7b7 100644
--- a/src/test/ui/consts/qualif_overwrite_2.stderr
+++ b/src/test/ui/consts/qualif_overwrite_2.stderr
@@ -1,5 +1,5 @@
 error[E0492]: cannot borrow a constant which may contain interior mutability, create a static instead
-  --> $DIR/qualif_overwrite_2.rs:8:5
+  --> $DIR/qualif_overwrite_2.rs:10:5
    |
 LL |     &{a.0} //~ ERROR cannot borrow a constant which may contain interior mutability
    |     ^^^^^^
diff --git a/src/test/ui/error-codes/E0010-teach.rs b/src/test/ui/error-codes/E0010-teach.rs
index 13371175f9c..e5ccf32af14 100644
--- a/src/test/ui/error-codes/E0010-teach.rs
+++ b/src/test/ui/error-codes/E0010-teach.rs
@@ -14,6 +14,5 @@
 #![allow(warnings)]
 
 const CON : Box<i32> = box 0; //~ ERROR E0010
-//~^ ERROR contains unimplemented expression type
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0010-teach.stderr b/src/test/ui/error-codes/E0010-teach.stderr
index 670698891d4..fa5c767caf2 100644
--- a/src/test/ui/error-codes/E0010-teach.stderr
+++ b/src/test/ui/error-codes/E0010-teach.stderr
@@ -6,16 +6,6 @@ LL | const CON : Box<i32> = box 0; //~ ERROR E0010
    |
    = note: The value of statics and constants must be known at compile time, and they live for the entire lifetime of a program. Creating a boxed value allocates memory on the heap at runtime, and therefore cannot be done at compile time.
 
-error[E0019]: constant contains unimplemented expression type
-  --> $DIR/E0010-teach.rs:16:28
-   |
-LL | const CON : Box<i32> = box 0; //~ ERROR E0010
-   |                            ^
-   |
-   = note: A function call isn't allowed in the const's initialization expression because the expression's value must be known at compile-time.
-   = note: Remember: you can't use a function call inside a const's initialization expression! However, you can use it anywhere else.
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0010, E0019.
-For more information about an error, try `rustc --explain E0010`.
+For more information about this error, try `rustc --explain E0010`.
diff --git a/src/test/ui/error-codes/E0010.rs b/src/test/ui/error-codes/E0010.rs
index 7a80b335c56..66a9319a7df 100644
--- a/src/test/ui/error-codes/E0010.rs
+++ b/src/test/ui/error-codes/E0010.rs
@@ -12,6 +12,5 @@
 #![allow(warnings)]
 
 const CON : Box<i32> = box 0; //~ ERROR E0010
-//~^ ERROR contains unimplemented expression type
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0010.stderr b/src/test/ui/error-codes/E0010.stderr
index 01295469b2b..83c1b409a51 100644
--- a/src/test/ui/error-codes/E0010.stderr
+++ b/src/test/ui/error-codes/E0010.stderr
@@ -4,13 +4,6 @@ error[E0010]: allocations are not allowed in constants
 LL | const CON : Box<i32> = box 0; //~ ERROR E0010
    |                        ^^^^^ allocation not allowed in constants
 
-error[E0019]: constant contains unimplemented expression type
-  --> $DIR/E0010.rs:14:28
-   |
-LL | const CON : Box<i32> = box 0; //~ ERROR E0010
-   |                            ^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0010, E0019.
-For more information about an error, try `rustc --explain E0010`.
+For more information about this error, try `rustc --explain E0010`.
diff --git a/src/test/ui/feature-gate-underscore_const_names.rs b/src/test/ui/feature-gate-underscore_const_names.rs
index 3724eaf61ca..b283e286514 100644
--- a/src/test/ui/feature-gate-underscore_const_names.rs
+++ b/src/test/ui/feature-gate-underscore_const_names.rs
@@ -7,6 +7,7 @@
 // <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(const_let)]
 
 trait Trt {}
 struct Str {}
diff --git a/src/test/ui/feature-gate-underscore_const_names.stderr b/src/test/ui/feature-gate-underscore_const_names.stderr
index 050ad871030..ab90ef8f11f 100644
--- a/src/test/ui/feature-gate-underscore_const_names.stderr
+++ b/src/test/ui/feature-gate-underscore_const_names.stderr
@@ -1,5 +1,5 @@
 error[E0658]: naming constants with `_` is unstable (see issue #54912)
-  --> $DIR/feature-gate-underscore_const_names.rs:16:1
+  --> $DIR/feature-gate-underscore_const_names.rs:17:1
    |
 LL | / const _ : () = {
 LL | |     use std::marker::PhantomData;
diff --git a/src/test/ui/feature-gates/feature-gate-const_let.rs b/src/test/ui/feature-gates/feature-gate-const_let.rs
new file mode 100644
index 00000000000..9bf957a5f1e
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-const_let.rs
@@ -0,0 +1,31 @@
+// Copyright 2018 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 let without feature gate.
+
+const FOO: usize = {
+    //~^ ERROR statements in constants are unstable
+    //~| ERROR: let bindings in constants are unstable
+    let x = 42;
+    //~^ ERROR statements in constants are unstable
+    //~| ERROR: let bindings in constants are unstable
+    42
+};
+
+static BAR: usize = {
+    //~^ ERROR statements in statics are unstable
+    //~| ERROR: let bindings in statics are unstable
+    let x = 42;
+    //~^ ERROR statements in statics are unstable
+    //~| ERROR: let bindings in statics are unstable
+    42
+};
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-18118.nll.stderr b/src/test/ui/issues/issue-18118.nll.stderr
index 9529b60c1b6..9e680e87f79 100644
--- a/src/test/ui/issues/issue-18118.nll.stderr
+++ b/src/test/ui/issues/issue-18118.nll.stderr
@@ -1,14 +1,68 @@
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:15:17
+   |
+LL |         let p = 3;
+   |                 ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:15:17
+   |
+LL |         let p = 3;
+   |                 ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:18:9
+   |
+LL |         &p //~ ERROR `p` does not live long enough
+   |         ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:12:5
+   |
+LL | /     const z: &'static isize = {
+LL | |         //~^ ERROR let bindings in constants are unstable
+LL | |         //~| ERROR statements in constants are unstable
+LL | |         let p = 3;
+...  |
+LL | |         //~^ ERROR let bindings in constants are unstable
+LL | |     };
+   | |______^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:12:5
+   |
+LL | /     const z: &'static isize = {
+LL | |         //~^ ERROR let bindings in constants are unstable
+LL | |         //~| ERROR statements in constants are unstable
+LL | |         let p = 3;
+...  |
+LL | |         //~^ ERROR let bindings in constants are unstable
+LL | |     };
+   | |______^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
 error[E0597]: `p` does not live long enough
-  --> $DIR/issue-18118.rs:14:9
+  --> $DIR/issue-18118.rs:18:9
    |
 LL |         &p //~ ERROR `p` does not live long enough
    |         ^^
    |         |
    |         borrowed value does not live long enough
    |         using this value as a constant requires that `p` is borrowed for `'static`
+LL |         //~^ ERROR let bindings in constants are unstable
 LL |     };
    |     - `p` dropped here while still borrowed
 
-error: aborting due to previous error
+error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0597`.
+Some errors occurred: E0597, E0658.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-18118.rs b/src/test/ui/issues/issue-18118.rs
index 05e46230db2..7194c159c1e 100644
--- a/src/test/ui/issues/issue-18118.rs
+++ b/src/test/ui/issues/issue-18118.rs
@@ -10,7 +10,12 @@
 
 pub fn main() {
     const z: &'static isize = {
+        //~^ ERROR let bindings in constants are unstable
+        //~| ERROR statements in constants are unstable
         let p = 3;
+        //~^ ERROR let bindings in constants are unstable
+        //~| ERROR statements in constants are unstable
         &p //~ ERROR `p` does not live long enough
+        //~^ ERROR let bindings in constants are unstable
     };
 }
diff --git a/src/test/ui/issues/issue-18118.stderr b/src/test/ui/issues/issue-18118.stderr
index 4f755745b28..2d83b86e5f4 100644
--- a/src/test/ui/issues/issue-18118.stderr
+++ b/src/test/ui/issues/issue-18118.stderr
@@ -1,13 +1,67 @@
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:15:17
+   |
+LL |         let p = 3;
+   |                 ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:15:17
+   |
+LL |         let p = 3;
+   |                 ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:18:9
+   |
+LL |         &p //~ ERROR `p` does not live long enough
+   |         ^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: let bindings in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:12:5
+   |
+LL | /     const z: &'static isize = {
+LL | |         //~^ ERROR let bindings in constants are unstable
+LL | |         //~| ERROR statements in constants are unstable
+LL | |         let p = 3;
+...  |
+LL | |         //~^ ERROR let bindings in constants are unstable
+LL | |     };
+   | |______^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/issue-18118.rs:12:5
+   |
+LL | /     const z: &'static isize = {
+LL | |         //~^ ERROR let bindings in constants are unstable
+LL | |         //~| ERROR statements in constants are unstable
+LL | |         let p = 3;
+...  |
+LL | |         //~^ ERROR let bindings in constants are unstable
+LL | |     };
+   | |______^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
 error[E0597]: `p` does not live long enough
-  --> $DIR/issue-18118.rs:14:10
+  --> $DIR/issue-18118.rs:18:10
    |
 LL |         &p //~ ERROR `p` does not live long enough
    |          ^ borrowed value does not live long enough
+LL |         //~^ ERROR let bindings in constants are unstable
 LL |     };
    |     - borrowed value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...
 
-error: aborting due to previous error
+error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0597`.
+Some errors occurred: E0597, E0658.
+For more information about an error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-32829-2.rs b/src/test/ui/issues/issue-32829-2.rs
index b5026d8c5e1..2b223bac8e6 100644
--- a/src/test/ui/issues/issue-32829-2.rs
+++ b/src/test/ui/issues/issue-32829-2.rs
@@ -15,6 +15,7 @@
 const bad : u32 = {
     {
         5;
+        //~^ ERROR statements in constants are unstable
         0
     }
 };
@@ -22,7 +23,8 @@ const bad : u32 = {
 const bad_two : u32 = {
     {
         invalid();
-        //~^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants
+        //~^ ERROR statements in constants are unstable
+        //~^^ ERROR: calls in constants are limited to constant functions, tuple structs and tuple variants
         0
     }
 };
@@ -30,6 +32,7 @@ const bad_two : u32 = {
 const bad_three : u32 = {
     {
         valid();
+        //~^ ERROR statements in constants are unstable
         0
     }
 };
@@ -37,6 +40,7 @@ const bad_three : u32 = {
 static bad_four : u32 = {
     {
         5;
+        //~^ ERROR statements in statics are unstable
         0
     }
 };
@@ -45,6 +49,7 @@ static bad_five : u32 = {
     {
         invalid();
         //~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
+        //~| ERROR statements in statics are unstable
         0
     }
 };
@@ -52,6 +57,7 @@ static bad_five : u32 = {
 static bad_six : u32 = {
     {
         valid();
+        //~^ ERROR statements in statics are unstable
         0
     }
 };
@@ -59,6 +65,7 @@ static bad_six : u32 = {
 static mut bad_seven : u32 = {
     {
         5;
+        //~^ ERROR statements in statics are unstable
         0
     }
 };
@@ -66,7 +73,8 @@ static mut bad_seven : u32 = {
 static mut bad_eight : u32 = {
     {
         invalid();
-        //~^ ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
+        //~^ ERROR statements in statics are unstable
+        //~| ERROR: calls in statics are limited to constant functions, tuple structs and tuple variants
         0
     }
 };
@@ -74,6 +82,7 @@ static mut bad_eight : u32 = {
 static mut bad_nine : u32 = {
     {
         valid();
+        //~^ ERROR statements in statics are unstable
         0
     }
 };
diff --git a/src/test/ui/issues/issue-32829-2.stderr b/src/test/ui/issues/issue-32829-2.stderr
index 5e5cdf8adda..6d6b94ca4bc 100644
--- a/src/test/ui/issues/issue-32829-2.stderr
+++ b/src/test/ui/issues/issue-32829-2.stderr
@@ -1,21 +1,94 @@
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:17:9
+   |
+LL |         5;
+   |         ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
 error[E0015]: calls in constants are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/issue-32829-2.rs:24:9
+  --> $DIR/issue-32829-2.rs:25:9
    |
 LL |         invalid();
    |         ^^^^^^^^^
 
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:25:9
+   |
+LL |         invalid();
+   |         ^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in constants are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:34:9
+   |
+LL |         valid();
+   |         ^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:42:9
+   |
+LL |         5;
+   |         ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/issue-32829-2.rs:46:9
+  --> $DIR/issue-32829-2.rs:50:9
    |
 LL |         invalid();
    |         ^^^^^^^^^
 
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:50:9
+   |
+LL |         invalid();
+   |         ^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:59:9
+   |
+LL |         valid();
+   |         ^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:67:9
+   |
+LL |         5;
+   |         ^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
 error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants
-  --> $DIR/issue-32829-2.rs:68:9
+  --> $DIR/issue-32829-2.rs:75:9
    |
 LL |         invalid();
    |         ^^^^^^^^^
 
-error: aborting due to 3 previous errors
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:75:9
+   |
+LL |         invalid();
+   |         ^^^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error[E0658]: statements in statics are unstable (see issue #48821)
+  --> $DIR/issue-32829-2.rs:84:9
+   |
+LL |         valid();
+   |         ^^^^^^^
+   |
+   = help: add #![feature(const_let)] to the crate attributes to enable
+
+error: aborting due to 12 previous errors
 
-For more information about this error, try `rustc --explain E0015`.
+Some errors occurred: E0015, E0658.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/issues/issue-37550.rs b/src/test/ui/issues/issue-37550.rs
index f6861b459d7..a2f40b3f539 100644
--- a/src/test/ui/issues/issue-37550.rs
+++ b/src/test/ui/issues/issue-37550.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 const fn x() {
-    let t = true;
-    let x = || t; //~ ERROR function pointers in const fn are unstable
+    let t = true; //~ ERROR local variables in const fn
+    let x = || t;
 }
 
 fn main() {}
diff --git a/src/test/ui/issues/issue-37550.stderr b/src/test/ui/issues/issue-37550.stderr
index 5b530de33f6..5a7d1ad043e 100644
--- a/src/test/ui/issues/issue-37550.stderr
+++ b/src/test/ui/issues/issue-37550.stderr
@@ -1,7 +1,7 @@
-error: function pointers in const fn are unstable
-  --> $DIR/issue-37550.rs:13:9
+error: local variables in const fn are unstable
+  --> $DIR/issue-37550.rs:12:9
    |
-LL |     let x = || t; //~ ERROR function pointers in const fn are unstable
+LL |     let t = true; //~ ERROR local variables in const fn
    |         ^
 
 error: aborting due to previous error
diff --git a/src/test/ui/issues/issue-7364.rs b/src/test/ui/issues/issue-7364.rs
index fca4fb62fad..801a1301ad7 100644
--- a/src/test/ui/issues/issue-7364.rs
+++ b/src/test/ui/issues/issue-7364.rs
@@ -16,6 +16,5 @@ 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>` cannot be shared between threads safely [E0277]
-//~| ERROR contains unimplemented expression type
 
 fn main() { }
diff --git a/src/test/ui/issues/issue-7364.stderr b/src/test/ui/issues/issue-7364.stderr
index b6594b1caca..b0d732bdb6f 100644
--- a/src/test/ui/issues/issue-7364.stderr
+++ b/src/test/ui/issues/issue-7364.stderr
@@ -4,12 +4,6 @@ error[E0010]: allocations are not allowed in statics
 LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
    |                                     ^^^^^^^^^^^^^^^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/issue-7364.rs:16:41
-   |
-LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
-   |                                         ^^^^^^^^^^^^^^^
-
 error[E0277]: `std::cell::RefCell<isize>` cannot be shared between threads safely
   --> $DIR/issue-7364.rs:16:1
    |
@@ -21,7 +15,7 @@ LL | static boxed: Box<RefCell<isize>> = box RefCell::new(0);
    = note: required because it appears within the type `std::boxed::Box<std::cell::RefCell<isize>>`
    = note: shared static variables must have a type that implements `Sync`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors occurred: E0010, E0019, E0277.
+Some errors occurred: E0010, E0277.
 For more information about an error, try `rustc --explain E0010`.
diff --git a/src/test/ui/static/static-mut-not-constant.rs b/src/test/ui/static/static-mut-not-constant.rs
index a25236b53b5..7e6ced12fe6 100644
--- a/src/test/ui/static/static-mut-not-constant.rs
+++ b/src/test/ui/static/static-mut-not-constant.rs
@@ -12,6 +12,5 @@
 
 static mut a: Box<isize> = box 3;
 //~^ ERROR allocations are not allowed in statics
-//~| ERROR static contains unimplemented expression
 
 fn main() {}
diff --git a/src/test/ui/static/static-mut-not-constant.stderr b/src/test/ui/static/static-mut-not-constant.stderr
index d9250e85d3e..ad44121e763 100644
--- a/src/test/ui/static/static-mut-not-constant.stderr
+++ b/src/test/ui/static/static-mut-not-constant.stderr
@@ -4,13 +4,6 @@ error[E0010]: allocations are not allowed in statics
 LL | static mut a: Box<isize> = box 3;
    |                            ^^^^^ allocation not allowed in statics
 
-error[E0019]: static contains unimplemented expression type
-  --> $DIR/static-mut-not-constant.rs:13:32
-   |
-LL | static mut a: Box<isize> = box 3;
-   |                                ^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors occurred: E0010, E0019.
-For more information about an error, try `rustc --explain E0010`.
+For more information about this error, try `rustc --explain E0010`.
diff --git a/src/test/ui/underscore_const_names.rs b/src/test/ui/underscore_const_names.rs
index bb123f46a57..8d31fd0b1e9 100644
--- a/src/test/ui/underscore_const_names.rs
+++ b/src/test/ui/underscore_const_names.rs
@@ -10,6 +10,7 @@
 
 // compile-pass
 
+#![feature(const_let)]
 #![feature(underscore_const_names)]
 
 trait Trt {}
diff --git a/src/test/ui/write-to-static-mut-in-static.rs b/src/test/ui/write-to-static-mut-in-static.rs
index 9a570a4381b..191f09b54ee 100644
--- a/src/test/ui/write-to-static-mut-in-static.rs
+++ b/src/test/ui/write-to-static-mut-in-static.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(const_let)]
+
 pub static mut A: u32 = 0;
 pub static mut B: () = unsafe { A = 1; };
 //~^ ERROR cannot mutate statics in the initializer of another static
diff --git a/src/test/ui/write-to-static-mut-in-static.stderr b/src/test/ui/write-to-static-mut-in-static.stderr
index e7233c5b8a5..673a71b4642 100644
--- a/src/test/ui/write-to-static-mut-in-static.stderr
+++ b/src/test/ui/write-to-static-mut-in-static.stderr
@@ -1,11 +1,11 @@
 error: cannot mutate statics in the initializer of another static
-  --> $DIR/write-to-static-mut-in-static.rs:12:33
+  --> $DIR/write-to-static-mut-in-static.rs:14:33
    |
 LL | pub static mut B: () = unsafe { A = 1; };
    |                                 ^^^^^
 
 error: cannot mutate statics in the initializer of another static
-  --> $DIR/write-to-static-mut-in-static.rs:15:34
+  --> $DIR/write-to-static-mut-in-static.rs:17:34
    |
 LL | pub static mut C: u32 = unsafe { C = 1; 0 };
    |                                  ^^^^^