about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <edy.burt@gmail.com>2017-02-20 03:55:28 +0200
committerEduard-Mihai Burtescu <edy.burt@gmail.com>2017-02-25 18:35:26 +0200
commitd9f0a949fd6b74641b12afc0f8a17f00919ebcef (patch)
tree6e05dba800cf05a891648e074cf6cd8782a0813f
parente7a48821c0d30ccd6b7ea88be24eed1bcba5f48a (diff)
downloadrust-d9f0a949fd6b74641b12afc0f8a17f00919ebcef.tar.gz
rust-d9f0a949fd6b74641b12afc0f8a17f00919ebcef.zip
rustc_const_eval: demand that the MIR qualify_consts ran on each evaluated body.
-rw-r--r--src/librustc/ty/maps.rs5
-rw-r--r--src/librustc_const_eval/eval.rs3
-rw-r--r--src/librustc_driver/driver.rs5
-rw-r--r--src/librustc_metadata/cstore_impl.rs1
-rw-r--r--src/librustc_metadata/decoder.rs17
-rw-r--r--src/librustc_metadata/encoder.rs13
-rw-r--r--src/librustc_metadata/schema.rs4
-rw-r--r--src/librustc_mir/lib.rs6
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs147
-rw-r--r--src/test/compile-fail/const-block-non-item-statement-2.rs26
-rw-r--r--src/test/compile-fail/const-block-non-item-statement.rs21
-rw-r--r--src/test/compile-fail/const-call.rs6
-rw-r--r--src/test/compile-fail/issue-39559.rs6
13 files changed, 148 insertions, 112 deletions
diff --git a/src/librustc/ty/maps.rs b/src/librustc/ty/maps.rs
index b79ab2a26fd..fd1403b15bc 100644
--- a/src/librustc/ty/maps.rs
+++ b/src/librustc/ty/maps.rs
@@ -361,6 +361,11 @@ define_maps! { <'tcx>
     /// (in the `RefCell` sense) to prevent accidental mutation.
     pub mir: Mir(DefId) -> &'tcx RefCell<mir::Mir<'tcx>>,
 
+    /// Maps DefId's that have an associated Mir to the result
+    /// of the MIR qualify_consts pass. The actual meaning of
+    /// the value isn't known except to the pass itself.
+    pub mir_const_qualif: Mir(DefId) -> u8,
+
     /// Records the type of each closure. The def ID is the ID of the
     /// expression defining the closure.
     pub closure_kind: ItemSignature(DefId) -> ty::ClosureKind,
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 284991a11b1..c5d577ce571 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -27,7 +27,7 @@ use rustc::util::nodemap::DefIdMap;
 use graphviz::IntoCow;
 use syntax::ast;
 use rustc::hir::{self, Expr};
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
 
 use std::borrow::Cow;
 use std::cmp::Ordering;
@@ -228,6 +228,7 @@ pub struct ConstContext<'a, 'tcx: 'a> {
 impl<'a, 'tcx> ConstContext<'a, 'tcx> {
     pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, body: hir::BodyId) -> Self {
         let def_id = tcx.hir.body_owner_def_id(body);
+        ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id);
         ConstContext::with_tables(tcx, tcx.item_tables(def_id))
     }
 
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 96824d19b90..ddf09f5cfe0 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -872,7 +872,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
     let index = stability::Index::new(&hir_map);
 
     let mut local_providers = ty::maps::Providers::default();
-    mir::mir_map::provide(&mut local_providers);
+    mir::provide(&mut local_providers);
     typeck::provide(&mut local_providers);
 
     let mut extern_providers = ty::maps::Providers::default();
@@ -958,8 +958,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
             // in stage 4 below.
             passes.push_hook(box mir::transform::dump_mir::DumpMir);
             passes.push_pass(box mir::transform::simplify::SimplifyCfg::new("initial"));
-            passes.push_pass(
-                box mir::transform::qualify_consts::QualifyAndPromoteConstants::default());
+            passes.push_pass(box mir::transform::qualify_consts::QualifyAndPromoteConstants);
             passes.push_pass(box mir::transform::type_check::TypeckMir);
             passes.push_pass(
                 box mir::transform::simplify_branches::SimplifyBranches::new("initial"));
diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs
index 443e75e63d3..7b02280ef90 100644
--- a/src/librustc_metadata/cstore_impl.rs
+++ b/src/librustc_metadata/cstore_impl.rs
@@ -101,6 +101,7 @@ provide! { <'tcx> tcx, def_id, cdata
 
         mir
     }
+    mir_const_qualif => { cdata.mir_const_qualif(def_id.index) }
     typeck_tables => { cdata.item_body_tables(def_id.index, tcx) }
     closure_kind => { cdata.closure_kind(def_id.index) }
     closure_type => { cdata.closure_ty(def_id.index, tcx) }
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index 1627b22cd5f..b4b9966cbe4 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -411,8 +411,8 @@ impl<'a, 'tcx> MetadataBlob {
 impl<'tcx> EntryKind<'tcx> {
     fn to_def(&self, did: DefId) -> Option<Def> {
         Some(match *self {
-            EntryKind::Const => Def::Const(did),
-            EntryKind::AssociatedConst(_) => Def::AssociatedConst(did),
+            EntryKind::Const(_) => Def::Const(did),
+            EntryKind::AssociatedConst(..) => Def::AssociatedConst(did),
             EntryKind::ImmStatic |
             EntryKind::ForeignImmStatic => Def::Static(did, false),
             EntryKind::MutStatic |
@@ -825,6 +825,17 @@ impl<'a, 'tcx> CrateMetadata {
         }
     }
 
+    pub fn mir_const_qualif(&self, id: DefIndex) -> u8 {
+        match self.entry(id).kind {
+            EntryKind::Const(qualif) |
+            EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif) |
+            EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif) => {
+                qualif
+            }
+            _ => bug!(),
+        }
+    }
+
     pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem {
         let item = self.entry(id);
         let def_key = self.def_key(id);
@@ -832,7 +843,7 @@ impl<'a, 'tcx> CrateMetadata {
         let name = def_key.disambiguated_data.data.get_opt_name().unwrap();
 
         let (kind, container, has_self) = match item.kind {
-            EntryKind::AssociatedConst(container) => {
+            EntryKind::AssociatedConst(container, _) => {
                 (ty::AssociatedKind::Const, container, false)
             }
             EntryKind::Method(data) => {
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index e73700f04fa..af0edab7a83 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -457,7 +457,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         };
 
         let kind = match trait_item.kind {
-            ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
+            ty::AssociatedKind::Const => {
+                EntryKind::AssociatedConst(container, 0)
+            }
             ty::AssociatedKind::Method => {
                 let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node {
                     let arg_names = match *m {
@@ -533,7 +535,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         };
 
         let kind = match impl_item.kind {
-            ty::AssociatedKind::Const => EntryKind::AssociatedConst(container),
+            ty::AssociatedKind::Const => {
+                EntryKind::AssociatedConst(container,
+                    ty::queries::mir_const_qualif::get(self.tcx, ast_item.span, def_id))
+            }
             ty::AssociatedKind::Method => {
                 let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node {
                     FnData {
@@ -637,7 +642,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         let kind = match item.node {
             hir::ItemStatic(_, hir::MutMutable, _) => EntryKind::MutStatic,
             hir::ItemStatic(_, hir::MutImmutable, _) => EntryKind::ImmStatic,
-            hir::ItemConst(..) => EntryKind::Const,
+            hir::ItemConst(..) => {
+                EntryKind::Const(ty::queries::mir_const_qualif::get(tcx, item.span, def_id))
+            }
             hir::ItemFn(_, _, constness, .., body) => {
                 let data = FnData {
                     constness: constness,
diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs
index 26d907523a8..4a20913d0b3 100644
--- a/src/librustc_metadata/schema.rs
+++ b/src/librustc_metadata/schema.rs
@@ -221,7 +221,7 @@ pub struct Entry<'tcx> {
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
 pub enum EntryKind<'tcx> {
-    Const,
+    Const(u8),
     ImmStatic,
     MutStatic,
     ForeignImmStatic,
@@ -243,7 +243,7 @@ pub enum EntryKind<'tcx> {
     DefaultImpl(Lazy<ImplData<'tcx>>),
     Method(Lazy<MethodData>),
     AssociatedType(AssociatedContainer),
-    AssociatedConst(AssociatedContainer),
+    AssociatedConst(AssociatedContainer, u8),
 }
 
 #[derive(RustcEncodable, RustcDecodable)]
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 9a8fb1099d0..a97495a0ebc 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -53,3 +53,9 @@ pub mod mir_map;
 pub mod pretty;
 pub mod transform;
 
+use rustc::ty::maps::Providers;
+
+pub fn provide(providers: &mut Providers) {
+    mir_map::provide(providers);
+    transform::qualify_consts::provide(providers);
+}
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 9f38564d1e2..441a9add883 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -16,24 +16,24 @@
 
 use rustc_data_structures::bitvec::BitVector;
 use rustc_data_structures::indexed_vec::{IndexVec, Idx};
+use rustc::dep_graph::DepNode;
 use rustc::hir;
 use rustc::hir::map as hir_map;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::traits::{self, Reveal};
-use rustc::ty::{self, TyCtxt, Ty};
+use rustc::ty::{self, TyCtxt, Ty, TypeFoldable};
 use rustc::ty::cast::CastTy;
+use rustc::ty::maps::Providers;
 use rustc::mir::*;
 use rustc::mir::traversal::ReversePostorder;
-use rustc::mir::transform::{Pass, MirPass, MirSource};
+use rustc::mir::transform::{Pass, MirMapPass, MirPassHook, MirSource};
 use rustc::mir::visit::{LvalueContext, Visitor};
-use rustc::util::nodemap::DefIdMap;
 use rustc::middle::lang_items;
 use syntax::abi::Abi;
 use syntax::feature_gate::UnstableFeatures;
-use syntax_pos::Span;
+use syntax_pos::{Span, DUMMY_SP};
 
-use std::collections::hash_map::Entry;
 use std::fmt;
 use std::usize;
 
@@ -41,36 +41,32 @@ use super::promote_consts::{self, Candidate, TempState};
 
 bitflags! {
     flags Qualif: u8 {
-        // Const item's qualification while recursing.
-        // Recursive consts are an error.
-        const RECURSIVE         = 1 << 0,
-
         // Constant containing interior mutability (UnsafeCell).
-        const MUTABLE_INTERIOR  = 1 << 1,
+        const MUTABLE_INTERIOR  = 1 << 0,
 
         // Constant containing an ADT that implements Drop.
-        const NEEDS_DROP        = 1 << 2,
+        const NEEDS_DROP        = 1 << 1,
 
         // Function argument.
-        const FN_ARGUMENT       = 1 << 3,
+        const FN_ARGUMENT       = 1 << 2,
 
         // Static lvalue or move from a static.
-        const STATIC            = 1 << 4,
+        const STATIC            = 1 << 3,
 
         // Reference to a static.
-        const STATIC_REF        = 1 << 5,
+        const STATIC_REF        = 1 << 4,
 
         // Not constant at all - non-`const fn` calls, asm!,
         // pointer comparisons, ptr-to-int casts, etc.
-        const NOT_CONST         = 1 << 6,
+        const NOT_CONST         = 1 << 5,
 
         // Refers to temporaries which cannot be promoted as
         // promote_consts decided they weren't simple enough.
-        const NOT_PROMOTABLE    = 1 << 7,
+        const NOT_PROMOTABLE    = 1 << 6,
 
         // Borrows of temporaries can be promoted only
         // if they have none of the above qualifications.
-        const NEVER_PROMOTE     = !0,
+        const NEVER_PROMOTE     = 0b111_1111,
 
         // Const items can only have MUTABLE_INTERIOR
         // and NOT_PROMOTABLE without producing an error.
@@ -134,7 +130,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     rpo: ReversePostorder<'a, 'tcx>,
     tcx: TyCtxt<'a, 'gcx, 'tcx>,
     param_env: ty::ParameterEnvironment<'tcx>,
-    qualif_map: &'a mut DefIdMap<Qualif>,
     temp_qualif: IndexVec<Local, Option<Qualif>>,
     return_qualif: Option<Qualif>,
     qualif: Qualif,
@@ -146,7 +141,6 @@ struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
     fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            param_env: ty::ParameterEnvironment<'tcx>,
-           qualif_map: &'a mut DefIdMap<Qualif>,
            def_id: DefId,
            mir: &'a Mir<'tcx>,
            mode: Mode)
@@ -162,7 +156,6 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
             rpo: rpo,
             tcx: tcx,
             param_env: param_env,
-            qualif_map: qualif_map,
             temp_qualif: IndexVec::from_elem(None, &mir.local_decls),
             return_qualif: None,
             qualif: Qualif::empty(),
@@ -585,17 +578,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
                     if substs.types().next().is_some() {
                         self.add_type(constant.ty);
                     } else {
-                        let qualif = qualify_const_item_cached(self.tcx,
-                                                               self.qualif_map,
-                                                               def_id);
-                        self.add(qualif);
-                    }
+                        let bits = ty::queries::mir_const_qualif::get(self.tcx,
+                                                                      constant.span,
+                                                                      def_id);
 
-                    // FIXME(eddyb) check recursive constants here,
-                    // instead of rustc_passes::static_recursion.
-                    if self.qualif.intersects(Qualif::RECURSIVE) {
-                        span_bug!(constant.span,
-                                  "recursive constant wasn't caught earlier");
+                        let qualif = Qualif::from_bits(bits).expect("invalid mir_const_qualif");
+                        self.add(qualif);
                     }
 
                     // Let `const fn` transitively have destructors,
@@ -944,41 +932,64 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
     }
 }
 
-fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                       qualif_map: &mut DefIdMap<Qualif>,
-                                       def_id: DefId)
-                                       -> Qualif {
-    match qualif_map.entry(def_id) {
-        Entry::Occupied(entry) => return *entry.get(),
-        Entry::Vacant(entry) => {
-            // Guard against `const` recursion.
-            entry.insert(Qualif::RECURSIVE);
-        }
+pub fn provide(providers: &mut Providers) {
+    providers.mir_const_qualif = qualify_const_item;
+}
+
+fn qualify_const_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                def_id: DefId)
+                                -> u8 {
+    let mir = &tcx.item_mir(def_id);
+    if mir.return_ty.references_error() {
+        return Qualif::NOT_CONST.bits();
     }
 
-    let param_env = if def_id.is_local() {
-        let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
-        ty::ParameterEnvironment::for_item(tcx, node_id)
-    } else {
-        // These should only be monomorphic constants.
-        tcx.empty_parameter_environment()
-    };
+    let node_id = tcx.hir.as_local_node_id(def_id).unwrap();
+    let param_env = ty::ParameterEnvironment::for_item(tcx, node_id);
 
-    let mir = &tcx.item_mir(def_id);
-    let mut qualifier = Qualifier::new(tcx, param_env, qualif_map, def_id, mir, Mode::Const);
-    let qualif = qualifier.qualify_const();
-    qualifier.qualif_map.insert(def_id, qualif);
-    qualif
+    let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, Mode::Const);
+    qualifier.qualify_const().bits()
 }
 
-#[derive(Default)]
-pub struct QualifyAndPromoteConstants {
-    qualif_map: DefIdMap<Qualif>
-}
+pub struct QualifyAndPromoteConstants;
 
 impl Pass for QualifyAndPromoteConstants {}
 
-impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
+impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
+    fn run_pass<'a>(&mut self,
+                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    hooks: &mut [Box<for<'s> MirPassHook<'s>>])
+    {
+        let def_ids = tcx.maps.mir.borrow().keys();
+        for def_id in def_ids {
+            if !def_id.is_local() {
+                continue;
+            }
+
+            let _task = tcx.dep_graph.in_task(DepNode::Mir(def_id));
+            let id = tcx.hir.as_local_node_id(def_id).unwrap();
+            let src = MirSource::from_node(tcx, id);
+
+            if let MirSource::Const(_) = src {
+                ty::queries::mir_const_qualif::get(tcx, DUMMY_SP, def_id);
+                continue;
+            }
+
+            let mir = &mut tcx.maps.mir.borrow()[&def_id].borrow_mut();
+            tcx.dep_graph.write(DepNode::Mir(def_id));
+
+            for hook in &mut *hooks {
+                hook.on_mir_pass(tcx, src, mir, self, false);
+            }
+            self.run_pass(tcx, src, mir);
+            for hook in &mut *hooks {
+                hook.on_mir_pass(tcx, src, mir, self, true);
+            }
+        }
+    }
+}
+
+impl<'tcx> QualifyAndPromoteConstants {
     fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     src: MirSource, mir: &mut Mir<'tcx>) {
         let id = src.item_id();
@@ -991,18 +1002,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
                     Mode::Fn
                 }
             }
-            MirSource::Const(_) => {
-                match self.qualif_map.entry(def_id) {
-                    Entry::Occupied(_) => return,
-                    Entry::Vacant(entry) => {
-                        // Guard against `const` recursion.
-                        entry.insert(Qualif::RECURSIVE);
-                        Mode::Const
-                    }
-                }
-            }
             MirSource::Static(_, hir::MutImmutable) => Mode::Static,
             MirSource::Static(_, hir::MutMutable) => Mode::StaticMut,
+            MirSource::Const(_) |
             MirSource::Promoted(..) => return
         };
         let param_env = ty::ParameterEnvironment::for_item(tcx, id);
@@ -1012,7 +1014,6 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
             // which can't be mutated until its scope ends.
             let (temps, candidates) = {
                 let mut qualifier = Qualifier::new(tcx, param_env,
-                                                   &mut self.qualif_map,
                                                    def_id, mir, mode);
                 if mode == Mode::ConstFn {
                     // Enforce a constant-like CFG for `const fn`.
@@ -1029,14 +1030,8 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants {
             // Do the actual promotion, now that we know what's viable.
             promote_consts::promote_candidates(mir, tcx, temps, candidates);
         } else {
-            let mut qualifier = Qualifier::new(tcx, param_env,
-                                               &mut self.qualif_map,
-                                               def_id, mir, mode);
-            let qualif = qualifier.qualify_const();
-
-            if mode == Mode::Const {
-                qualifier.qualif_map.insert(def_id, qualif);
-            }
+            let mut qualifier = Qualifier::new(tcx, param_env, def_id, mir, mode);
+            qualifier.qualify_const();
         }
 
         // Statics must be Sync.
diff --git a/src/test/compile-fail/const-block-non-item-statement-2.rs b/src/test/compile-fail/const-block-non-item-statement-2.rs
new file mode 100644
index 00000000000..83166c9bd4b
--- /dev/null
+++ b/src/test/compile-fail/const-block-non-item-statement-2.rs
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+const A: usize = { 1; 2 };
+//~^ ERROR: blocks in constants are limited to items and tail expressions
+
+const B: usize = { { } 2 };
+//~^ ERROR: blocks in constants are limited to items and tail expressions
+
+macro_rules! foo {
+    () => (()) //~ ERROR: blocks in constants are limited to items and tail expressions
+}
+const C: usize = { foo!(); 2 };
+
+const D: usize = { let x = 4; 2 };
+//~^ ERROR: blocks in constants are limited to items and tail expressions
+//~^^ ERROR: blocks in constants are limited to items and tail expressions
+
+pub fn main() {}
diff --git a/src/test/compile-fail/const-block-non-item-statement.rs b/src/test/compile-fail/const-block-non-item-statement.rs
index edb85023c9b..bdc69c937c6 100644
--- a/src/test/compile-fail/const-block-non-item-statement.rs
+++ b/src/test/compile-fail/const-block-non-item-statement.rs
@@ -8,21 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-const A: usize = { 1; 2 };
-//~^ ERROR: blocks in constants are limited to items and tail expressions
-
-const B: usize = { { } 2 };
-//~^ ERROR: blocks in constants are limited to items and tail expressions
-
-macro_rules! foo {
-    () => (()) //~ ERROR: blocks in constants are limited to items and tail expressions
-}
-const C: usize = { foo!(); 2 };
-
-const D: usize = { let x = 4; 2 };
-//~^ ERROR: blocks in constants are limited to items and tail expressions
-//~^^ ERROR: blocks in constants are limited to items and tail expressions
-
 enum Foo {
     Bar = { let x = 1; 3 }
     //~^ ERROR: blocks in constants are limited to items and tail expressions
@@ -33,8 +18,4 @@ type Array = [u32; {  let x = 2; 5 }];
 //~^ ERROR: blocks in constants are limited to items and tail expressions
 //~^^ ERROR: blocks in constants are limited to items and tail expressions
 
-pub fn main() {
-    let _: Array = [0; { let x = 3; 5 }];
-    //~^ ERROR: blocks in constants are limited to items and tail expressions
-    //~^^ ERROR: blocks in constants are limited to items and tail expressions
-}
+pub fn main() {}
diff --git a/src/test/compile-fail/const-call.rs b/src/test/compile-fail/const-call.rs
index 7e2eabf412d..ff83dd004a2 100644
--- a/src/test/compile-fail/const-call.rs
+++ b/src/test/compile-fail/const-call.rs
@@ -15,6 +15,8 @@ fn f(x: usize) -> usize {
 }
 
 fn main() {
-    let _ = [0; f(2)]; //~ ERROR constant evaluation error [E0080]
-                       //~| non-constant path in constant expression
+    let _ = [0; f(2)];
+    //~^ ERROR calls in constants are limited to constant functions
+    //~| ERROR constant evaluation error [E0080]
+    //~| non-constant path in constant expression
 }
diff --git a/src/test/compile-fail/issue-39559.rs b/src/test/compile-fail/issue-39559.rs
index bc492806b96..06e8406cbc0 100644
--- a/src/test/compile-fail/issue-39559.rs
+++ b/src/test/compile-fail/issue-39559.rs
@@ -27,9 +27,11 @@ pub struct Vector<T, D: Dim> {
 
 fn main() {
     let array: [usize; Dim3::dim()]
-    //~^ ERROR constant evaluation error
+    //~^ ERROR calls in constants are limited to constant functions
+    //~| ERROR constant evaluation error
     //~| non-constant path in constant expression
         = [0; Dim3::dim()];
-        //~^ ERROR constant evaluation error
+        //~^ ERROR calls in constants are limited to constant functions
+        //~| ERROR constant evaluation error
         //~| non-constant path in constant expression
 }