about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2014-12-30 22:36:03 +0200
committerEduard Burtescu <edy.burt@gmail.com>2015-02-16 16:29:21 +0200
commit4d8f995c3a482fecdb9a77455cd8d68d514d62ac (patch)
treeb0e8399e734c0be82e21481db5f3e5a28024caa2
parent8dd1f6a0dc59236caffb483fdb0176df1945062f (diff)
downloadrust-4d8f995c3a482fecdb9a77455cd8d68d514d62ac.tar.gz
rust-4d8f995c3a482fecdb9a77455cd8d68d514d62ac.zip
rustc: merge check_static into check_const.
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/middle/check_const.rs349
-rw-r--r--src/librustc/middle/check_static.rs342
-rw-r--r--src/librustc_driver/driver.rs3
-rw-r--r--src/test/compile-fail/check-static-immutable-mut-slices.rs2
-rw-r--r--src/test/compile-fail/check-static-values-constraints.rs15
-rw-r--r--src/test/compile-fail/issue-17458.rs2
-rw-r--r--src/test/compile-fail/issue-17718-const-bad-values.rs4
-rw-r--r--src/test/compile-fail/issue-18118.rs3
-rw-r--r--src/test/compile-fail/issue-7364.rs3
-rw-r--r--src/test/compile-fail/static-mut-not-constant.rs2
11 files changed, 316 insertions, 410 deletions
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index f060d464e41..abf70813d36 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -90,7 +90,6 @@ pub mod middle {
     pub mod check_loop;
     pub mod check_match;
     pub mod check_rvalues;
-    pub mod check_static;
     pub mod const_eval;
     pub mod dataflow;
     pub mod dead;
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index b558f838a51..34d1654ec4b 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -1,4 +1,4 @@
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -8,44 +8,117 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// Verifies that the types and values of const and static items
+// are safe. The rules enforced by this module are:
+//
+// - For each *mutable* static item, it checks that its **type**:
+//     - doesn't have a destructor
+//     - doesn't own an owned pointer
+//
+// - For each *immutable* static item, it checks that its **value**:
+//       - doesn't own owned, managed pointers
+//       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
+//           - the type of the struct/enum has a dtor
+//
+// Rules Enforced Elsewhere:
+// - It's not possible to take the address of a static item with unsafe interior. This is enforced
+// by borrowck::gather_loans
 
-use middle::def::*;
+use self::Mode::*;
+
+use middle::def;
+use middle::expr_use_visitor as euv;
+use middle::infer;
+use middle::mem_categorization as mc;
+use middle::traits;
 use middle::ty;
 use util::ppaux;
 
 use syntax::ast;
+use syntax::codemap::Span;
+use syntax::print::pprust;
 use syntax::visit::{self, Visitor};
 
+#[derive(Copy, Eq, PartialEq)]
+enum Mode {
+    InConstant,
+    InStatic,
+    InStaticMut,
+    InNothing,
+}
+
 struct CheckCrateVisitor<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-    in_const: bool
+    mode: Mode,
 }
 
 impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
-    fn with_const<F>(&mut self, in_const: bool, f: F) where
+    fn with_mode<F>(&mut self, mode: Mode, f: F) where
         F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
     {
-        let was_const = self.in_const;
-        self.in_const = in_const;
+        let old = self.mode;
+        self.mode = mode;
         f(self);
-        self.in_const = was_const;
+        self.mode = old;
     }
-    fn inside_const<F>(&mut self, f: F) where
-        F: FnOnce(&mut CheckCrateVisitor<'a, 'tcx>),
-    {
-        self.with_const(true, f);
+
+    fn msg(&self) -> &'static str {
+        match self.mode {
+            InConstant => "constant",
+            InStaticMut | InStatic => "static",
+            InNothing => unreachable!(),
+        }
+    }
+
+    fn check_static_mut_type(&self, e: &ast::Expr) {
+        let node_ty = ty::node_id_to_type(self.tcx, e.id);
+        let tcontents = ty::type_contents(self.tcx, node_ty);
+
+        let suffix = if tcontents.has_dtor() {
+            "destructors"
+        } else if tcontents.owns_owned() {
+            "owned pointers"
+        } else {
+            return
+        };
+
+        self.tcx.sess.span_err(e.span, &format!("mutable statics are not allowed \
+                                                 to have {}", suffix)[]);
+    }
+
+    fn check_static_type(&self, e: &ast::Expr) {
+        let ty = ty::node_id_to_type(self.tcx, e.id);
+        let infcx = infer::new_infer_ctxt(self.tcx);
+        let mut fulfill_cx = traits::FulfillmentContext::new();
+        let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
+        fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
+        let env = ty::empty_parameter_environment(self.tcx);
+        match fulfill_cx.select_all_or_error(&infcx, &env) {
+            Ok(()) => { },
+            Err(ref errors) => {
+                traits::report_fulfillment_errors(&infcx, errors);
+            }
+        }
     }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
     fn visit_item(&mut self, i: &ast::Item) {
+        debug!("visit_item(item={})", pprust::item_to_string(i));
         match i.node {
-            ast::ItemStatic(_, _, ref ex) |
-            ast::ItemConst(_, ref ex) => {
-                self.inside_const(|v| v.visit_expr(&**ex));
+            ast::ItemStatic(_, ast::MutImmutable, ref expr) => {
+                self.check_static_type(&**expr);
+                self.with_mode(InStatic, |v| v.visit_expr(&**expr));
+            }
+            ast::ItemStatic(_, ast::MutMutable, ref expr) => {
+                self.check_static_mut_type(&**expr);
+                self.with_mode(InStaticMut, |v| v.visit_expr(&**expr));
+            }
+            ast::ItemConst(_, ref expr) => {
+                self.with_mode(InConstant, |v| v.visit_expr(&**expr));
             }
             ast::ItemEnum(ref enum_definition, _) => {
-                self.inside_const(|v| {
+                self.with_mode(InConstant, |v| {
                     for var in &enum_definition.variants {
                         if let Some(ref ex) = var.node.disr_expr {
                             v.visit_expr(&**ex);
@@ -53,46 +126,60 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                     }
                 });
             }
-            _ => self.with_const(false, |v| visit::walk_item(v, i))
+            _ => {
+                self.with_mode(InNothing, |v| visit::walk_item(v, i));
+            }
         }
     }
+
     fn visit_pat(&mut self, p: &ast::Pat) {
-        let is_const = match p.node {
-            ast::PatLit(_) | ast::PatRange(..) => true,
-            _ => false
+        let mode = match p.node {
+            ast::PatLit(_) | ast::PatRange(..) => InConstant,
+            _ => InNothing
         };
-        self.with_const(is_const, |v| visit::walk_pat(v, p))
+        self.with_mode(mode, |v| visit::walk_pat(v, p))
     }
+
     fn visit_expr(&mut self, ex: &ast::Expr) {
-        if self.in_const {
+        if self.mode != InNothing {
             check_expr(self, ex);
         }
         visit::walk_expr(self, ex);
     }
 }
 
-pub fn check_crate(tcx: &ty::ctxt) {
-    visit::walk_crate(&mut CheckCrateVisitor { tcx: tcx, in_const: false },
-                      tcx.map.krate());
-    tcx.sess.abort_if_errors();
-}
-
+/// This function is used to enforce the constraints on
+/// const/static items. It walks through the *value*
+/// of the item walking down the expression and evaluating
+/// every nested expression. If the expression is not part
+/// of a const/static item, this function does nothing but
+/// walking down through it.
 fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
+    let node_ty = ty::node_id_to_type(v.tcx, e.id);
+
+    match node_ty.sty {
+        ty::ty_struct(did, _) |
+        ty::ty_enum(did, _) if ty::has_dtor(v.tcx, did) => {
+            v.tcx.sess.span_err(e.span,
+                                &format!("{}s are not allowed to have destructors",
+                                         v.msg())[])
+        }
+        _ => {}
+    }
+
     match e.node {
-        ast::ExprUnary(ast::UnDeref, _) => {}
+        ast::ExprBox(..) |
         ast::ExprUnary(ast::UnUniq, _) => {
             span_err!(v.tcx.sess, e.span, E0010,
-                      "cannot do allocations in constant expressions");
+                      "allocations are not allowed in {}s", v.msg());
         }
         ast::ExprBinary(..) | ast::ExprUnary(..) => {
             let method_call = ty::MethodCall::expr(e.id);
             if v.tcx.method_map.borrow().contains_key(&method_call) {
                 span_err!(v.tcx.sess, e.span, E0011,
-                          "user-defined operators are not allowed in constant \
-                           expressions");
+                          "user-defined operators are not allowed in {}s", v.msg());
             }
         }
-        ast::ExprLit(_) => {}
         ast::ExprCast(ref from, _) => {
             let toty = ty::expr_ty(v.tcx, e);
             let fromty = ty::expr_ty(v.tcx, &**from);
@@ -102,20 +189,24 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
                 (ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty));
             if !is_legal_cast {
                 span_err!(v.tcx.sess, e.span, E0012,
-                          "can not cast to `{}` in a constant expression",
-                          ppaux::ty_to_string(v.tcx, toty));
+                          "can not cast to `{}` in {}s",
+                          ppaux::ty_to_string(v.tcx, toty), v.msg());
             }
             if ty::type_is_unsafe_ptr(fromty) && ty::type_is_numeric(toty) {
                 span_err!(v.tcx.sess, e.span, E0018,
-                          "can not cast a pointer to an integer in a constant \
-                           expression");
+                          "can not cast a pointer to an integer in {}s", v.msg());
             }
         }
         ast::ExprPath(_) | ast::ExprQPath(_) => {
             match v.tcx.def_map.borrow()[e.id] {
-                DefStatic(..) | DefConst(..) |
-                DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
-                DefStruct(_) | DefVariant(_, _, _) => {}
+                def::DefStatic(..) if v.mode == InConstant => {
+                    span_err!(v.tcx.sess, e.span, E0013,
+                              "constants cannot refer to other statics, \
+                               insert an intermediate constant instead");
+                }
+                def::DefStatic(..) | def::DefConst(..) |
+                def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) |
+                def::DefStruct(_) | def::DefVariant(_, _, _) => {}
 
                 def => {
                     debug!("(checking const) found bad def: {:?}", def);
@@ -127,7 +218,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
         }
         ast::ExprCall(ref callee, _) => {
             match v.tcx.def_map.borrow()[callee.id] {
-                DefStruct(..) | DefVariant(..) => {}    // OK.
+                def::DefStruct(..) | def::DefVariant(..) => {}    // OK.
                 _ => {
                     span_err!(v.tcx.sess, e.span, E0015,
                               "function calls in constants are limited to \
@@ -160,6 +251,17 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
                 }
             }
         }
+        ast::ExprAddrOf(ast::MutMutable, ref inner) => {
+            match inner.node {
+                // Mutable slices are allowed. Only in `static mut`.
+                ast::ExprVec(_) if v.mode == InStaticMut => {}
+                _ => span_err!(v.tcx.sess, e.span, E0017,
+                               "references in {}s may only refer \
+                                to immutable values", v.msg())
+            }
+        }
+
+        ast::ExprLit(_) |
         ast::ExprVec(_) |
         ast::ExprAddrOf(ast::MutImmutable, _) |
         ast::ExprParen(..) |
@@ -170,18 +272,165 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
         ast::ExprRepeat(..) |
         ast::ExprStruct(..) => {}
 
-        ast::ExprAddrOf(_, ref inner) => {
-            match inner.node {
-                // Mutable slices are allowed.
-                ast::ExprVec(_) => {}
-                _ => span_err!(v.tcx.sess, e.span, E0017,
-                               "references in constants may only refer \
-                                to immutable values")
+        // Conditional control flow (possible to implement).
+        ast::ExprMatch(..) |
+        ast::ExprIf(..) |
+        ast::ExprIfLet(..) |
 
-            }
+        // Loops (not very meaningful in constants).
+        ast::ExprWhile(..) |
+        ast::ExprWhileLet(..) |
+        ast::ExprForLoop(..) |
+        ast::ExprLoop(..) |
+
+        // More control flow (also not very meaningful).
+        ast::ExprBreak(_) |
+        ast::ExprAgain(_) |
+        ast::ExprRet(_) |
+
+        // Miscellaneous expressions that could be implemented.
+        ast::ExprClosure(..) |
+        ast::ExprRange(..) |
+
+        // Various other expressions.
+        ast::ExprMethodCall(..) |
+        ast::ExprAssign(..) |
+        ast::ExprAssignOp(..) |
+        ast::ExprInlineAsm(_) |
+        ast::ExprMac(_) => {
+            span_err!(v.tcx.sess, e.span, E0019,
+                      "{} contains unimplemented expression type", v.msg());
         }
+    }
+}
 
-        _ => span_err!(v.tcx.sess, e.span, E0019,
-                       "constant contains unimplemented expression type")
+struct GlobalVisitor<'a,'b,'tcx:'a+'b>(
+    euv::ExprUseVisitor<'a,'b,'tcx,ty::ParameterEnvironment<'b,'tcx>>);
+
+struct GlobalChecker<'a,'tcx:'a> {
+    tcx: &'a ty::ctxt<'tcx>
+}
+
+pub fn check_crate(tcx: &ty::ctxt) {
+    let param_env = ty::empty_parameter_environment(tcx);
+    let mut checker = GlobalChecker {
+        tcx: tcx
+    };
+    let visitor = euv::ExprUseVisitor::new(&mut checker, &param_env);
+    visit::walk_crate(&mut GlobalVisitor(visitor), tcx.map.krate());
+
+    visit::walk_crate(&mut CheckCrateVisitor {
+        tcx: tcx,
+        mode: InNothing,
+    }, tcx.map.krate());
+
+    tcx.sess.abort_if_errors();
+}
+
+impl<'a,'b,'t,'v> Visitor<'v> for GlobalVisitor<'a,'b,'t> {
+    fn visit_item(&mut self, item: &ast::Item) {
+        match item.node {
+            ast::ItemConst(_, ref e) |
+            ast::ItemStatic(_, _, ref e) => {
+                let GlobalVisitor(ref mut v) = *self;
+                v.consume_expr(&**e);
+            }
+            _ => {}
+        }
+        visit::walk_item(self, item);
     }
 }
+
+impl<'a, 'tcx> euv::Delegate<'tcx> for GlobalChecker<'a, 'tcx> {
+    fn consume(&mut self,
+               _consume_id: ast::NodeId,
+               consume_span: Span,
+               cmt: mc::cmt,
+               _mode: euv::ConsumeMode) {
+        let mut cur = &cmt;
+        loop {
+            match cur.cat {
+                mc::cat_static_item => {
+                    // statics cannot be consumed by value at any time, that would imply
+                    // that they're an initializer (what a const is for) or kept in sync
+                    // over time (not feasible), so deny it outright.
+                    self.tcx.sess.span_err(consume_span,
+                        "cannot refer to other statics by value, use the \
+                         address-of operator or a constant instead");
+                    break;
+                }
+                mc::cat_deref(ref cmt, _, _) |
+                mc::cat_downcast(ref cmt, _) |
+                mc::cat_interior(ref cmt, _) => cur = cmt,
+
+                mc::cat_rvalue(..) |
+                mc::cat_upvar(..) |
+                mc::cat_local(..) => break
+            }
+        }
+    }
+    fn borrow(&mut self,
+              _borrow_id: ast::NodeId,
+              borrow_span: Span,
+              cmt: mc::cmt<'tcx>,
+              _loan_region: ty::Region,
+              _bk: ty::BorrowKind,
+              _loan_cause: euv::LoanCause) {
+        let mut cur = &cmt;
+        let mut is_interior = false;
+        loop {
+            match cur.cat {
+                mc::cat_rvalue(..) => {
+                    // constants cannot be borrowed if they contain interior mutability as
+                    // it means that our "silent insertion of statics" could change
+                    // initializer values (very bad).
+                    if ty::type_contents(self.tcx, cur.ty).interior_unsafe() {
+                        self.tcx.sess.span_err(borrow_span,
+                            "cannot borrow a constant which contains \
+                            interior mutability, create a static instead");
+                    }
+                    break;
+                }
+                mc::cat_static_item => {
+                    if is_interior {
+                        // Borrowed statics can specifically *only* have their address taken,
+                        // not any number of other borrows such as borrowing fields, reading
+                        // elements of an array, etc.
+                        self.tcx.sess.span_err(borrow_span,
+                            "cannot refer to the interior of another \
+                             static, use a constant instead");
+                    }
+                    break;
+                }
+                mc::cat_deref(ref cmt, _, _) |
+                mc::cat_downcast(ref cmt, _) |
+                mc::cat_interior(ref cmt, _) => {
+                    is_interior = true;
+                    cur = cmt;
+                }
+
+                mc::cat_upvar(..) |
+                mc::cat_local(..) => break
+            }
+        }
+    }
+
+    fn decl_without_init(&mut self,
+                         _id: ast::NodeId,
+                         _span: Span) {}
+    fn mutate(&mut self,
+              _assignment_id: ast::NodeId,
+              _assignment_span: Span,
+              _assignee_cmt: mc::cmt,
+              _mode: euv::MutateMode) {}
+
+    fn matched_pat(&mut self,
+                   _: &ast::Pat,
+                   _: mc::cmt,
+                   _: euv::MatchMode) {}
+
+    fn consume_pat(&mut self,
+                   _consume_pat: &ast::Pat,
+                   _cmt: mc::cmt,
+                   _mode: euv::ConsumeMode) {}
+}
\ No newline at end of file
diff --git a/src/librustc/middle/check_static.rs b/src/librustc/middle/check_static.rs
deleted file mode 100644
index ac0caebd6cf..00000000000
--- a/src/librustc/middle/check_static.rs
+++ /dev/null
@@ -1,342 +0,0 @@
-// 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.
-
-// Verifies that the types and values of static items
-// are safe. The rules enforced by this module are:
-//
-// - For each *mutable* static item, it checks that its **type**:
-//     - doesn't have a destructor
-//     - doesn't own an owned pointer
-//
-// - For each *immutable* static item, it checks that its **value**:
-//       - doesn't own owned, managed pointers
-//       - doesn't contain a struct literal or a call to an enum variant / struct constructor where
-//           - the type of the struct/enum has a dtor
-//
-// Rules Enforced Elsewhere:
-// - It's not possible to take the address of a static item with unsafe interior. This is enforced
-// by borrowck::gather_loans
-use self::Mode::*;
-
-use middle::ty;
-use middle::def;
-use middle::infer;
-use middle::traits;
-use middle::mem_categorization as mc;
-use middle::expr_use_visitor as euv;
-use util::nodemap::NodeSet;
-
-use syntax::ast;
-use syntax::print::pprust;
-use syntax::visit::Visitor;
-use syntax::codemap::Span;
-use syntax::visit;
-
-#[derive(Copy, Eq, PartialEq)]
-enum Mode {
-    InConstant,
-    InStatic,
-    InStaticMut,
-    InNothing,
-}
-
-struct CheckStaticVisitor<'a, 'tcx: 'a> {
-    tcx: &'a ty::ctxt<'tcx>,
-    mode: Mode,
-    checker: &'a mut GlobalChecker,
-}
-
-struct GlobalVisitor<'a,'b,'tcx:'a+'b>(
-    euv::ExprUseVisitor<'a,'b,'tcx,ty::ParameterEnvironment<'b,'tcx>>);
-struct GlobalChecker {
-    static_consumptions: NodeSet,
-    const_borrows: NodeSet,
-    static_interior_borrows: NodeSet,
-    static_local_borrows: NodeSet,
-}
-
-pub fn check_crate(tcx: &ty::ctxt) {
-    let mut checker = GlobalChecker {
-        static_consumptions: NodeSet(),
-        const_borrows: NodeSet(),
-        static_interior_borrows: NodeSet(),
-        static_local_borrows: NodeSet(),
-    };
-    {
-        let param_env = ty::empty_parameter_environment(tcx);
-        let visitor = euv::ExprUseVisitor::new(&mut checker, &param_env);
-        visit::walk_crate(&mut GlobalVisitor(visitor), tcx.map.krate());
-    }
-    visit::walk_crate(&mut CheckStaticVisitor {
-        tcx: tcx,
-        mode: InNothing,
-        checker: &mut checker,
-    }, tcx.map.krate());
-    tcx.sess.abort_if_errors();
-}
-
-impl<'a, 'tcx> CheckStaticVisitor<'a, 'tcx> {
-    fn with_mode<F>(&mut self, mode: Mode, f: F) where
-        F: FnOnce(&mut CheckStaticVisitor<'a, 'tcx>),
-    {
-        let old = self.mode;
-        self.mode = mode;
-        f(self);
-        self.mode = old;
-    }
-
-    fn msg(&self) -> &'static str {
-        match self.mode {
-            InConstant => "constants",
-            InStaticMut | InStatic => "statics",
-            InNothing => unreachable!(),
-        }
-    }
-
-    fn check_static_mut_type(&self, e: &ast::Expr) {
-        let node_ty = ty::node_id_to_type(self.tcx, e.id);
-        let tcontents = ty::type_contents(self.tcx, node_ty);
-
-        let suffix = if tcontents.has_dtor() {
-            "destructors"
-        } else if tcontents.owns_owned() {
-            "owned pointers"
-        } else {
-            return
-        };
-
-        self.tcx.sess.span_err(e.span, &format!("mutable statics are not allowed \
-                                                to have {}", suffix)[]);
-    }
-
-    fn check_static_type(&self, e: &ast::Expr) {
-        let ty = ty::node_id_to_type(self.tcx, e.id);
-        let infcx = infer::new_infer_ctxt(self.tcx);
-        let mut fulfill_cx = traits::FulfillmentContext::new();
-        let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
-        fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
-        let env = ty::empty_parameter_environment(self.tcx);
-        match fulfill_cx.select_all_or_error(&infcx, &env) {
-            Ok(()) => { },
-            Err(ref errors) => {
-                traits::report_fulfillment_errors(&infcx, errors);
-            }
-        }
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for CheckStaticVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, i: &ast::Item) {
-        debug!("visit_item(item={})", pprust::item_to_string(i));
-        match i.node {
-            ast::ItemStatic(_, ast::MutImmutable, ref expr) => {
-                self.check_static_type(&**expr);
-                self.with_mode(InStatic, |v| v.visit_expr(&**expr));
-            }
-            ast::ItemStatic(_, ast::MutMutable, ref expr) => {
-                self.check_static_mut_type(&**expr);
-                self.with_mode(InStaticMut, |v| v.visit_expr(&**expr));
-            }
-            ast::ItemConst(_, ref expr) => {
-                self.with_mode(InConstant, |v| v.visit_expr(&**expr));
-            }
-            _ => {
-                self.with_mode(InNothing, |v| visit::walk_item(v, i));
-            }
-        }
-    }
-
-    /// This method is used to enforce the constraints on
-    /// immutable static items. It walks through the *value*
-    /// of the item walking down the expression and evaluating
-    /// every nested expression. if the expression is not part
-    /// of a static item, this method does nothing but walking
-    /// down through it.
-    fn visit_expr(&mut self, e: &ast::Expr) {
-        if self.mode == InNothing {
-            return visit::walk_expr(self, e);
-        }
-
-        let node_ty = ty::node_id_to_type(self.tcx, e.id);
-
-        match node_ty.sty {
-            ty::ty_struct(did, _) |
-            ty::ty_enum(did, _) if ty::has_dtor(self.tcx, did) => {
-                self.tcx.sess.span_err(e.span,
-                                       &format!("{} are not allowed to have \
-                                                destructors", self.msg())[])
-            }
-            _ => {}
-        }
-
-        // statics cannot be consumed by value at any time, that would imply
-        // that they're an initializer (what a const is for) or kept in sync
-        // over time (not feasible), so deny it outright.
-        if self.checker.static_consumptions.remove(&e.id) {
-            self.tcx.sess.span_err(e.span, "cannot refer to other statics by \
-                                            value, use the address-of operator \
-                                            or a constant instead");
-        }
-
-        // Borrowed statics can specifically *only* have their address taken,
-        // not any number of other borrows such as borrowing fields, reading
-        // elements of an array, etc.
-        if self.checker.static_interior_borrows.remove(&e.id) {
-            self.tcx.sess.span_err(e.span, "cannot refer to the interior of \
-                                            another static, use a constant \
-                                            instead");
-        }
-
-        // constants cannot be borrowed if they contain interior mutability as
-        // it means that our "silent insertion of statics" could change
-        // initializer values (very bad).
-        if self.checker.const_borrows.remove(&e.id) {
-            let node_ty = ty::node_id_to_type(self.tcx, e.id);
-            let tcontents = ty::type_contents(self.tcx, node_ty);
-            if tcontents.interior_unsafe() {
-                self.tcx.sess.span_err(e.span, "cannot borrow a constant which \
-                                                contains interior mutability, \
-                                                create a static instead");
-            }
-        }
-
-        // local variables in a block expression in a static context (i.e. being
-        // assigned to a static variable) cannot be borrowed.
-        if self.checker.static_local_borrows.remove(&e.id) {
-            self.tcx.sess.span_err(e.span, "cannot borrow a local variable inside \
-                                            a static block, define a separate static \
-                                            instead");
-        }
-
-        match e.node {
-            ast::ExprAddrOf(ast::MutMutable, _) => {
-                if self.mode != InStaticMut {
-                    span_err!(self.tcx.sess, e.span, E0020,
-                              "{} are not allowed to have mutable references",
-                              self.msg());
-                }
-            },
-            ast::ExprBox(..) |
-            ast::ExprUnary(ast::UnUniq, _) => {
-                span_err!(self.tcx.sess, e.span, E0022,
-                          "{} are not allowed to have custom pointers",
-                          self.msg());
-            }
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
-                match ty::resolve_expr(self.tcx, e) {
-                    def::DefStatic(..) if self.mode == InConstant => {
-                        let msg = "constants cannot refer to other statics, \
-                                   insert an intermediate constant \
-                                   instead";
-                        self.tcx.sess.span_err(e.span, &msg[]);
-                    }
-                    _ => {}
-                }
-            }
-            _ => {}
-        }
-        visit::walk_expr(self, e);
-    }
-}
-
-impl<'a,'b,'t,'v> Visitor<'v> for GlobalVisitor<'a,'b,'t> {
-    fn visit_item(&mut self, item: &ast::Item) {
-        match item.node {
-            ast::ItemConst(_, ref e) |
-            ast::ItemStatic(_, _, ref e) => {
-                let GlobalVisitor(ref mut v) = *self;
-                v.consume_expr(&**e);
-            }
-            _ => {}
-        }
-        visit::walk_item(self, item);
-    }
-}
-
-impl<'tcx> euv::Delegate<'tcx> for GlobalChecker {
-    fn consume(&mut self,
-               consume_id: ast::NodeId,
-               _consume_span: Span,
-               cmt: mc::cmt,
-               _mode: euv::ConsumeMode) {
-        let mut cur = &cmt;
-        loop {
-            match cur.cat {
-                mc::cat_static_item => {
-                    self.static_consumptions.insert(consume_id);
-                    break
-                }
-                mc::cat_deref(ref cmt, _, _) |
-                mc::cat_downcast(ref cmt, _) |
-                mc::cat_interior(ref cmt, _) => cur = cmt,
-
-                mc::cat_rvalue(..) |
-                mc::cat_upvar(..) |
-                mc::cat_local(..) => break,
-            }
-        }
-    }
-    fn borrow(&mut self,
-              borrow_id: ast::NodeId,
-              _borrow_span: Span,
-              cmt: mc::cmt,
-              _loan_region: ty::Region,
-              _bk: ty::BorrowKind,
-              _loan_cause: euv::LoanCause) {
-        let mut cur = &cmt;
-        let mut is_interior = false;
-        loop {
-            match cur.cat {
-                mc::cat_rvalue(..) => {
-                    self.const_borrows.insert(borrow_id);
-                    break
-                }
-                mc::cat_static_item => {
-                    if is_interior {
-                        self.static_interior_borrows.insert(borrow_id);
-                    }
-                    break
-                }
-                mc::cat_deref(ref cmt, _, _) |
-                mc::cat_interior(ref cmt, _) => {
-                    is_interior = true;
-                    cur = cmt;
-                }
-
-                mc::cat_downcast(..) |
-                mc::cat_upvar(..) => unreachable!(),
-
-                mc::cat_local(..) => {
-                    self.static_local_borrows.insert(borrow_id);
-                    break
-                }
-            }
-        }
-    }
-
-    fn decl_without_init(&mut self,
-                         _id: ast::NodeId,
-                         _span: Span) {}
-    fn mutate(&mut self,
-              _assignment_id: ast::NodeId,
-              _assignment_span: Span,
-              _assignee_cmt: mc::cmt,
-              _mode: euv::MutateMode) {}
-
-    fn matched_pat(&mut self,
-                   _: &ast::Pat,
-                   _: mc::cmt,
-                   _: euv::MatchMode) {}
-
-    fn consume_pat(&mut self,
-                   _consume_pat: &ast::Pat,
-                   _cmt: mc::cmt,
-                   _mode: euv::ConsumeMode) {}
-}
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index c0c464a4f51..c3e205e050f 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -611,9 +611,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     // passes are timed inside typeck
     typeck::check_crate(&ty_cx, trait_map);
 
-    time(time_passes, "check static items", (), |_|
-         middle::check_static::check_crate(&ty_cx));
-
     time(time_passes, "const checking", (), |_|
          middle::check_const::check_crate(&ty_cx));
 
diff --git a/src/test/compile-fail/check-static-immutable-mut-slices.rs b/src/test/compile-fail/check-static-immutable-mut-slices.rs
index d1e3fe25253..1804b9e04c2 100644
--- a/src/test/compile-fail/check-static-immutable-mut-slices.rs
+++ b/src/test/compile-fail/check-static-immutable-mut-slices.rs
@@ -11,6 +11,6 @@
 // Checks that immutable static items can't have mutable slices
 
 static TEST: &'static mut [isize] = &mut [];
-//~^ ERROR statics are not allowed to have mutable references
+//~^ ERROR references in statics may only refer to immutable values
 
 pub fn main() { }
diff --git a/src/test/compile-fail/check-static-values-constraints.rs b/src/test/compile-fail/check-static-values-constraints.rs
index 7c4f9ada2d3..0180bccbca4 100644
--- a/src/test/compile-fail/check-static-values-constraints.rs
+++ b/src/test/compile-fail/check-static-values-constraints.rs
@@ -99,7 +99,7 @@ static STATIC10: UnsafeStruct = UnsafeStruct;
 struct MyOwned;
 
 static STATIC11: Box<MyOwned> = box MyOwned;
-//~^ ERROR statics are not allowed to have custom pointers
+//~^ ERROR allocations are not allowed in statics
 
 // The following examples test that mutable structs are just forbidden
 // to have types with destructors
@@ -117,16 +117,17 @@ static mut STATIC14: SafeStruct = SafeStruct {
 //~^ ERROR mutable statics are not allowed to have destructors
     field1: SafeEnum::Variant1,
     field2: SafeEnum::Variant4("str".to_string())
+//~^ ERROR static contains unimplemented expression type
 };
 
 static STATIC15: &'static [Box<MyOwned>] = &[
-    box MyOwned, //~ ERROR statics are not allowed to have custom pointers
-    box MyOwned, //~ ERROR statics are not allowed to have custom pointers
+    box MyOwned, //~ ERROR allocations are not allowed in statics
+    box MyOwned, //~ ERROR allocations are not allowed in statics
 ];
 
 static STATIC16: (&'static Box<MyOwned>, &'static Box<MyOwned>) = (
-    &box MyOwned, //~ ERROR statics are not allowed to have custom pointers
-    &box MyOwned, //~ ERROR statics are not allowed to have custom pointers
+    &box MyOwned, //~ ERROR allocations are not allowed in statics
+    &box MyOwned, //~ ERROR allocations are not allowed in statics
 );
 
 static mut STATIC17: SafeEnum = SafeEnum::Variant1;
@@ -134,9 +135,9 @@ static mut STATIC17: SafeEnum = SafeEnum::Variant1;
 
 static STATIC19: Box<isize> =
     box 3;
-//~^ ERROR statics are not allowed to have custom pointers
+//~^ ERROR allocations are not allowed in statics
 
 pub fn main() {
     let y = { static x: Box<isize> = box 3; x };
-    //~^ ERROR statics are not allowed to have custom pointers
+    //~^ ERROR allocations are not allowed in statics
 }
diff --git a/src/test/compile-fail/issue-17458.rs b/src/test/compile-fail/issue-17458.rs
index d9fd67f9197..d6f70ae1e57 100644
--- a/src/test/compile-fail/issue-17458.rs
+++ b/src/test/compile-fail/issue-17458.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 static X: usize = 0 as *const usize as usize;
-//~^ ERROR: can not cast a pointer to an integer in a constant expression
+//~^ ERROR: can not cast a pointer to an integer in statics
 
 fn main() {
     assert_eq!(X, 0);
diff --git a/src/test/compile-fail/issue-17718-const-bad-values.rs b/src/test/compile-fail/issue-17718-const-bad-values.rs
index daa250d12f5..2347d3f3d5c 100644
--- a/src/test/compile-fail/issue-17718-const-bad-values.rs
+++ b/src/test/compile-fail/issue-17718-const-bad-values.rs
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 const C1: &'static mut [usize] = &mut [];
-//~^ ERROR: constants are not allowed to have mutable references
+//~^ ERROR: references in constants may only refer to immutable values
 
 static mut S: usize = 3;
 const C2: &'static mut usize = &mut S;
 //~^ ERROR: constants cannot refer to other statics
-//~^^ ERROR: are not allowed to have mutable references
+//~^^ ERROR: references in constants may only refer to immutable values
 
 fn main() {}
 
diff --git a/src/test/compile-fail/issue-18118.rs b/src/test/compile-fail/issue-18118.rs
index 129f28f1d89..53df24d5b00 100644
--- a/src/test/compile-fail/issue-18118.rs
+++ b/src/test/compile-fail/issue-18118.rs
@@ -11,7 +11,8 @@
 pub fn main() {
     static z: &'static isize = {
         let p = 3;
+        //~^ ERROR blocks in constants are limited to items and tail expressions
         &p
-//~^ ERROR cannot borrow a local variable inside a static block, define a separate static instead
+        //~^ ERROR paths in constants may only refer to constants or functions
     };
 }
diff --git a/src/test/compile-fail/issue-7364.rs b/src/test/compile-fail/issue-7364.rs
index 465a38111ba..8744afe2339 100644
--- a/src/test/compile-fail/issue-7364.rs
+++ b/src/test/compile-fail/issue-7364.rs
@@ -14,8 +14,9 @@ use std::cell::RefCell;
 
 // Regression test for issue 7364
 static boxed: Box<RefCell<isize>> = box RefCell::new(0);
-//~^ ERROR statics are not allowed to have custom pointers
+//~^ ERROR allocations are not allowed in statics
 //~| ERROR: the trait `core::marker::Sync` is not implemented for the type
 //~| ERROR: the trait `core::marker::Sync` is not implemented for the type
+//~^^^^^ ERROR function calls in constants are limited to struct and enum constructors
 
 fn main() { }
diff --git a/src/test/compile-fail/static-mut-not-constant.rs b/src/test/compile-fail/static-mut-not-constant.rs
index 7c228ce413f..08148328edc 100644
--- a/src/test/compile-fail/static-mut-not-constant.rs
+++ b/src/test/compile-fail/static-mut-not-constant.rs
@@ -11,7 +11,7 @@
 #![feature(box_syntax)]
 
 static mut a: Box<isize> = box 3;
-//~^ ERROR statics are not allowed to have custom pointers
+//~^ ERROR allocations are not allowed in statics
 //~^^ ERROR mutable statics are not allowed to have owned pointers
 
 fn main() {}