about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/cfg/construct.rs6
-rw-r--r--src/librustc/dep_graph/edges.rs2
-rw-r--r--src/librustc/dep_graph/thread.rs2
-rw-r--r--src/librustc/front/map/blocks.rs10
-rw-r--r--src/librustc/front/map/mod.rs40
-rw-r--r--src/librustc/infer/combine.rs6
-rw-r--r--src/librustc/infer/error_reporting.rs2
-rw-r--r--src/librustc/infer/freshen.rs9
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs22
-rw-r--r--src/librustc/infer/mod.rs15
-rw-r--r--src/librustc/infer/region_inference/graphviz.rs6
-rw-r--r--src/librustc/infer/region_inference/mod.rs44
-rw-r--r--src/librustc/infer/resolve.rs4
-rw-r--r--src/librustc/infer/type_variable.rs8
-rw-r--r--src/librustc/lint/context.rs20
-rw-r--r--src/librustc/macros.rs15
-rw-r--r--src/librustc/middle/astconv_util.rs3
-rw-r--r--src/librustc/middle/cstore.rs140
-rw-r--r--src/librustc/middle/dead.rs4
-rw-r--r--src/librustc/middle/def.rs6
-rw-r--r--src/librustc/middle/expr_use_visitor.rs30
-rw-r--r--src/librustc/middle/free_region.rs9
-rw-r--r--src/librustc/middle/intrinsicck.rs6
-rw-r--r--src/librustc/middle/liveness.rs31
-rw-r--r--src/librustc/middle/mem_categorization.rs46
-rw-r--r--src/librustc/middle/reachable.rs15
-rw-r--r--src/librustc/middle/region.rs12
-rw-r--r--src/librustc/middle/resolve_lifetime.rs8
-rw-r--r--src/librustc/middle/stability.rs18
-rw-r--r--src/librustc/mir/repr.rs2
-rw-r--r--src/librustc/mir/tcx.rs2
-rw-r--r--src/librustc/session/config.rs2
-rw-r--r--src/librustc/session/filesearch.rs4
-rw-r--r--src/librustc/session/mod.rs53
-rw-r--r--src/librustc/traits/coherence.rs4
-rw-r--r--src/librustc/traits/error_reporting.rs15
-rw-r--r--src/librustc/traits/project.rs31
-rw-r--r--src/librustc/traits/select.rs72
-rw-r--r--src/librustc/traits/specialize/mod.rs6
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs4
-rw-r--r--src/librustc/traits/util.rs4
-rw-r--r--src/librustc/ty/adjustment.rs26
-rw-r--r--src/librustc/ty/contents.rs2
-rw-r--r--src/librustc/ty/context.rs12
-rw-r--r--src/librustc/ty/mod.rs80
-rw-r--r--src/librustc/ty/relate.rs2
-rw-r--r--src/librustc/ty/sty.rs15
-rw-r--r--src/librustc/ty/subst.rs36
-rw-r--r--src/librustc/ty/util.rs12
-rw-r--r--src/librustc_borrowck/borrowck/fragments.rs13
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs4
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs6
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/move_error.rs9
-rw-r--r--src/librustc_borrowck/borrowck/mir/gather_moves.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs26
-rw-r--r--src/librustc_borrowck/borrowck/move_data.rs2
-rw-r--r--src/librustc_borrowck/lib.rs1
-rw-r--r--src/librustc_const_eval/check_match.rs61
-rw-r--r--src/librustc_const_eval/eval.rs26
-rw-r--r--src/librustc_const_eval/lib.rs2
-rw-r--r--src/librustc_lint/bad_style.rs2
-rw-r--r--src/librustc_lint/types.rs14
-rw-r--r--src/librustc_metadata/astencode.rs16
-rw-r--r--src/librustc_metadata/creader.rs6
-rw-r--r--src/librustc_metadata/decoder.rs64
-rw-r--r--src/librustc_metadata/encoder.rs2
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_metadata/loader.rs11
-rw-r--r--src/librustc_metadata/tydecode.rs32
-rw-r--r--src/librustc_metadata/tyencode.rs4
-rw-r--r--src/librustc_mir/build/expr/as_constant.rs5
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs2
-rw-r--r--src/librustc_mir/build/matches/mod.rs8
-rw-r--r--src/librustc_mir/build/matches/test.rs5
-rw-r--r--src/librustc_mir/build/mod.rs4
-rw-r--r--src/librustc_mir/build/scope.rs16
-rw-r--r--src/librustc_mir/hair/cx/expr.rs61
-rw-r--r--src/librustc_mir/hair/cx/mod.rs9
-rw-r--r--src/librustc_mir/hair/cx/pattern.rs33
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/librustc_mir/mir_map.rs3
-rw-r--r--src/librustc_passes/const_fn.rs6
-rw-r--r--src/librustc_passes/consts.rs6
-rw-r--r--src/librustc_passes/lib.rs2
-rw-r--r--src/librustc_passes/static_recursion.rs18
-rw-r--r--src/librustc_privacy/lib.rs2
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs2
-rw-r--r--src/librustc_resolve/lib.rs25
-rw-r--r--src/librustc_save_analysis/data.rs11
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs55
-rw-r--r--src/librustc_save_analysis/lib.rs50
-rw-r--r--src/librustc_save_analysis/span_utils.rs26
-rw-r--r--src/librustc_trans/_match.rs14
-rw-r--r--src/librustc_trans/abi.rs6
-rw-r--r--src/librustc_trans/adt.rs31
-rw-r--r--src/librustc_trans/assert_dep_graph.rs2
-rw-r--r--src/librustc_trans/back/link.rs10
-rw-r--r--src/librustc_trans/back/linker.rs4
-rw-r--r--src/librustc_trans/back/symbol_names.rs4
-rw-r--r--src/librustc_trans/back/write.rs6
-rw-r--r--src/librustc_trans/base.rs86
-rw-r--r--src/librustc_trans/build.rs2
-rw-r--r--src/librustc_trans/builder.rs10
-rw-r--r--src/librustc_trans/cabi_aarch64.rs4
-rw-r--r--src/librustc_trans/cabi_arm.rs6
-rw-r--r--src/librustc_trans/cabi_mips.rs4
-rw-r--r--src/librustc_trans/cabi_powerpc.rs4
-rw-r--r--src/librustc_trans/cabi_powerpc64.rs4
-rw-r--r--src/librustc_trans/cabi_x86_64.rs12
-rw-r--r--src/librustc_trans/callee.rs30
-rw-r--r--src/librustc_trans/cleanup.rs14
-rw-r--r--src/librustc_trans/closure.rs7
-rw-r--r--src/librustc_trans/collector.rs23
-rw-r--r--src/librustc_trans/common.rs23
-rw-r--r--src/librustc_trans/consts.rs80
-rw-r--r--src/librustc_trans/context.rs4
-rw-r--r--src/librustc_trans/controlflow.rs2
-rw-r--r--src/librustc_trans/datum.rs4
-rw-r--r--src/librustc_trans/debuginfo/create_scope_map.rs2
-rw-r--r--src/librustc_trans/debuginfo/gdb.rs2
-rw-r--r--src/librustc_trans/debuginfo/metadata.rs159
-rw-r--r--src/librustc_trans/debuginfo/mod.rs38
-rw-r--r--src/librustc_trans/debuginfo/namespace.rs6
-rw-r--r--src/librustc_trans/debuginfo/type_names.rs6
-rw-r--r--src/librustc_trans/debuginfo/utils.rs4
-rw-r--r--src/librustc_trans/declare.rs6
-rw-r--r--src/librustc_trans/expr.rs141
-rw-r--r--src/librustc_trans/glue.rs4
-rw-r--r--src/librustc_trans/inline.rs8
-rw-r--r--src/librustc_trans/intrinsic.rs34
-rw-r--r--src/librustc_trans/lib.rs2
-rw-r--r--src/librustc_trans/meth.rs20
-rw-r--r--src/librustc_trans/mir/block.rs10
-rw-r--r--src/librustc_trans/mir/constant.rs4
-rw-r--r--src/librustc_trans/mir/lvalue.rs4
-rw-r--r--src/librustc_trans/mir/mod.rs2
-rw-r--r--src/librustc_trans/mir/operand.rs5
-rw-r--r--src/librustc_trans/mir/rvalue.rs22
-rw-r--r--src/librustc_trans/mir/statement.rs6
-rw-r--r--src/librustc_trans/monomorphize.rs4
-rw-r--r--src/librustc_trans/tvec.rs16
-rw-r--r--src/librustc_trans/type_.rs4
-rw-r--r--src/librustc_trans/type_of.rs15
-rw-r--r--src/librustc_typeck/astconv.rs14
-rw-r--r--src/librustc_typeck/check/_match.rs5
-rw-r--r--src/librustc_typeck/check/callee.rs2
-rw-r--r--src/librustc_typeck/check/cast.rs2
-rw-r--r--src/librustc_typeck/check/coercion.rs3
-rw-r--r--src/librustc_typeck/check/dropck.rs11
-rw-r--r--src/librustc_typeck/check/method/confirm.rs30
-rw-r--r--src/librustc_typeck/check/method/mod.rs14
-rw-r--r--src/librustc_typeck/check/method/probe.rs6
-rw-r--r--src/librustc_typeck/check/mod.rs34
-rw-r--r--src/librustc_typeck/check/op.rs7
-rw-r--r--src/librustc_typeck/check/regionck.rs35
-rw-r--r--src/librustc_typeck/check/upvar.rs6
-rw-r--r--src/librustc_typeck/check/wfcheck.rs6
-rw-r--r--src/librustc_typeck/coherence/mod.rs17
-rw-r--r--src/librustc_typeck/collect.rs42
-rw-r--r--src/librustc_typeck/lib.rs16
-rw-r--r--src/librustc_typeck/variance/constraints.rs30
161 files changed, 1326 insertions, 1451 deletions
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index e75625f7fae..cd1e3b5f30e 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -583,13 +583,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
                         return *l;
                     }
                 }
-                self.tcx.sess.span_bug(expr.span,
-                    &format!("no loop scope for id {}", loop_id));
+                span_bug!(expr.span, "no loop scope for id {}", loop_id);
             }
 
             r => {
-                self.tcx.sess.span_bug(expr.span,
-                    &format!("bad entry `{:?}` in def_map for label", r));
+                span_bug!(expr.span, "bad entry `{:?}` in def_map for label", r);
             }
         }
     }
diff --git a/src/librustc/dep_graph/edges.rs b/src/librustc/dep_graph/edges.rs
index 4b25285c476..d3ced8aa518 100644
--- a/src/librustc/dep_graph/edges.rs
+++ b/src/librustc/dep_graph/edges.rs
@@ -122,7 +122,7 @@ impl DepGraphEdges {
     {
         match self.current_node() {
             Some(open_node) => self.add_edge_from_open_node(open_node, op),
-            None => panic!("no current node, cannot add edge into dependency graph")
+            None => bug!("no current node, cannot add edge into dependency graph")
         }
     }
 
diff --git a/src/librustc/dep_graph/thread.rs b/src/librustc/dep_graph/thread.rs
index c43b4b15b76..1b1d3469bc5 100644
--- a/src/librustc/dep_graph/thread.rs
+++ b/src/librustc/dep_graph/thread.rs
@@ -148,7 +148,7 @@ impl DepGraphThreadData {
 
     // Outline this too.
     fn invalid_message(&self, string: &str) {
-        panic!("{}; see src/librustc/dep_graph/README.md for more information", string)
+        bug!("{}; see src/librustc/dep_graph/README.md for more information", string)
     }
 }
 
diff --git a/src/librustc/front/map/blocks.rs b/src/librustc/front/map/blocks.rs
index 976a8c6dda0..2eb3d56bb5e 100644
--- a/src/librustc/front/map/blocks.rs
+++ b/src/librustc/front/map/blocks.rs
@@ -231,13 +231,13 @@ impl<'a> FnLikeNode<'a> {
                         span: i.span,
                         attrs: &i.attrs,
                     }),
-                _ => panic!("item FnLikeNode that is not fn-like"),
+                _ => bug!("item FnLikeNode that is not fn-like"),
             },
             map::NodeTraitItem(ti) => match ti.node {
                 ast::MethodTraitItem(ref sig, Some(ref body)) => {
                     method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs)
                 }
-                _ => panic!("trait method FnLikeNode that is not fn-like"),
+                _ => bug!("trait method FnLikeNode that is not fn-like"),
             },
             map::NodeImplItem(ii) => {
                 match ii.node {
@@ -245,7 +245,7 @@ impl<'a> FnLikeNode<'a> {
                         method(ii.id, ii.name, sig, Some(ii.vis), body, ii.span, &ii.attrs)
                     }
                     _ => {
-                        panic!("impl method FnLikeNode that is not fn-like")
+                        bug!("impl method FnLikeNode that is not fn-like")
                     }
                 }
             }
@@ -256,9 +256,9 @@ impl<'a> FnLikeNode<'a> {
                                               e.id,
                                               e.span,
                                               e.attrs.as_attr_slice())),
-                _ => panic!("expr FnLikeNode that is not fn-like"),
+                _ => bug!("expr FnLikeNode that is not fn-like"),
             },
-            _ => panic!("other FnLikeNode that is not fn-like"),
+            _ => bug!("other FnLikeNode that is not fn-like"),
         }
     }
 }
diff --git a/src/librustc/front/map/mod.rs b/src/librustc/front/map/mod.rs
index 3605de44495..817bec58407 100644
--- a/src/librustc/front/map/mod.rs
+++ b/src/librustc/front/map/mod.rs
@@ -335,9 +335,9 @@ impl<'ast> Map<'ast> {
                     return self.opt_local_def_id(id)
                                .map(|def_id| DepNode::Hir(def_id))
                                .unwrap_or_else(|| {
-                                   panic!("Walking parents from `{}` \
-                                           led to `NotPresent` at `{}`",
-                                          id0, id)
+                                   bug!("Walking parents from `{}` \
+                                         led to `NotPresent` at `{}`",
+                                        id0, id)
                                }),
             }
         }
@@ -363,8 +363,8 @@ impl<'ast> Map<'ast> {
 
     pub fn local_def_id(&self, node: NodeId) -> DefId {
         self.opt_local_def_id(node).unwrap_or_else(|| {
-            panic!("local_def_id: no entry for `{}`, which has a map of `{:?}`",
-                   node, self.find_entry(node))
+            bug!("local_def_id: no entry for `{}`, which has a map of `{:?}`",
+                 node, self.find_entry(node))
         })
     }
 
@@ -402,7 +402,7 @@ impl<'ast> Map<'ast> {
     pub fn get(&self, id: NodeId) -> Node<'ast> {
         match self.find(id) {
             Some(node) => node, // read recorded by `find`
-            None => panic!("couldn't find node id {} in the AST map", id)
+            None => bug!("couldn't find node id {} in the AST map", id)
         }
     }
 
@@ -576,7 +576,7 @@ impl<'ast> Map<'ast> {
                 self.read(id); // reveals some of the content of a node
                 abi
             }
-            None => panic!("expected foreign mod or inlined parent, found {}",
+            None => bug!("expected foreign mod or inlined parent, found {}",
                           self.node_to_string(parent))
         }
     }
@@ -584,14 +584,14 @@ impl<'ast> Map<'ast> {
     pub fn expect_item(&self, id: NodeId) -> &'ast Item {
         match self.find(id) { // read recorded by `find`
             Some(NodeItem(item)) => item,
-            _ => panic!("expected item, found {}", self.node_to_string(id))
+            _ => bug!("expected item, found {}", self.node_to_string(id))
         }
     }
 
     pub fn expect_trait_item(&self, id: NodeId) -> &'ast TraitItem {
         match self.find(id) {
             Some(NodeTraitItem(item)) => item,
-            _ => panic!("expected trait item, found {}", self.node_to_string(id))
+            _ => bug!("expected trait item, found {}", self.node_to_string(id))
         }
     }
 
@@ -600,38 +600,38 @@ impl<'ast> Map<'ast> {
             Some(NodeItem(i)) => {
                 match i.node {
                     ItemStruct(ref struct_def, _) => struct_def,
-                    _ => panic!("struct ID bound to non-struct")
+                    _ => bug!("struct ID bound to non-struct")
                 }
             }
             Some(NodeVariant(variant)) => {
                 if variant.node.data.is_struct() {
                     &variant.node.data
                 } else {
-                    panic!("struct ID bound to enum variant that isn't struct-like")
+                    bug!("struct ID bound to enum variant that isn't struct-like")
                 }
             }
-            _ => panic!(format!("expected struct, found {}", self.node_to_string(id))),
+            _ => bug!("expected struct, found {}", self.node_to_string(id)),
         }
     }
 
     pub fn expect_variant(&self, id: NodeId) -> &'ast Variant {
         match self.find(id) {
             Some(NodeVariant(variant)) => variant,
-            _ => panic!(format!("expected variant, found {}", self.node_to_string(id))),
+            _ => bug!("expected variant, found {}", self.node_to_string(id)),
         }
     }
 
     pub fn expect_foreign_item(&self, id: NodeId) -> &'ast ForeignItem {
         match self.find(id) {
             Some(NodeForeignItem(item)) => item,
-            _ => panic!("expected foreign item, found {}", self.node_to_string(id))
+            _ => bug!("expected foreign item, found {}", self.node_to_string(id))
         }
     }
 
     pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
         match self.find(id) { // read recorded by find
             Some(NodeExpr(expr)) => expr,
-            _ => panic!("expected expr, found {}", self.node_to_string(id))
+            _ => bug!("expected expr, found {}", self.node_to_string(id))
         }
     }
 
@@ -656,7 +656,7 @@ impl<'ast> Map<'ast> {
             NodeLocal(&Pat { node: PatKind::Ident(_,l,_), .. }) => {
                 PathName(l.node.name)
             },
-            _ => panic!("no path elem for {:?}", node)
+            _ => bug!("no path elem for {:?}", node)
         }
     }
 
@@ -773,7 +773,7 @@ impl<'ast> Map<'ast> {
     pub fn span(&self, id: NodeId) -> Span {
         self.read(id); // reveals span from node
         self.opt_span(id)
-            .unwrap_or_else(|| panic!("AstMap.span: could not find span for id {:?}", id))
+            .unwrap_or_else(|| bug!("AstMap.span: could not find span for id {:?}", id))
     }
 
     pub fn span_if_local(&self, id: DefId) -> Option<Span> {
@@ -1019,12 +1019,12 @@ impl<'a> NodePrinter for pprust::State<'a> {
             NodePat(a)         => self.print_pat(&a),
             NodeBlock(a)       => self.print_block(&a),
             NodeLifetime(a)    => self.print_lifetime(&a),
-            NodeTyParam(_)     => panic!("cannot print TyParam"),
+            NodeTyParam(_)     => bug!("cannot print TyParam"),
             // these cases do not carry enough information in the
             // ast_map to reconstruct their full structure for pretty
             // printing.
-            NodeLocal(_)       => panic!("cannot print isolated Local"),
-            NodeStructCtor(_)  => panic!("cannot print isolated StructCtor"),
+            NodeLocal(_)       => bug!("cannot print isolated Local"),
+            NodeStructCtor(_)  => bug!("cannot print isolated StructCtor"),
         }
     }
 }
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index 2b30698882d..8edf24fbc25 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -339,10 +339,10 @@ impl<'cx, 'tcx> ty::fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> {
             // Early-bound regions should really have been substituted away before
             // we get to this point.
             ty::ReEarlyBound(..) => {
-                self.tcx().sess.span_bug(
+                span_bug!(
                     self.span,
-                    &format!("Encountered early bound region when generalizing: {:?}",
-                            r));
+                    "Encountered early bound region when generalizing: {:?}",
+                    r);
             }
 
             // Always make a fresh region variable for skolemized regions;
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 20c01344144..8079a6d1bbc 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -404,7 +404,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     bound_failures.push((origin.clone(), kind.clone(), region));
                 }
                 ProcessedErrors(..) => {
-                    panic!("should not encounter a `ProcessedErrors` yet: {:?}", error)
+                    bug!("should not encounter a `ProcessedErrors` yet: {:?}", error)
                 }
             }
         }
diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs
index 352733a595d..b0f1e9d890c 100644
--- a/src/librustc/infer/freshen.rs
+++ b/src/librustc/infer/freshen.rs
@@ -140,11 +140,10 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
             ty::TyInfer(ty::FreshIntTy(c)) |
             ty::TyInfer(ty::FreshFloatTy(c)) => {
                 if c >= self.freshen_count {
-                    tcx.sess.bug(
-                        &format!("Encountered a freshend type with id {} \
-                                  but our counter is only at {}",
-                                 c,
-                                 self.freshen_count));
+                    bug!("Encountered a freshend type with id {} \
+                          but our counter is only at {}",
+                         c,
+                         self.freshen_count);
                 }
                 t
             }
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index db4ee17bafb..d89ef8ef6c3 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -183,11 +183,10 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
                 }
             }
 
-            infcx.tcx.sess.span_bug(
+            span_bug!(
                 span,
-                &format!("region {:?} is not associated with \
-                         any bound region from A!",
-                        r0))
+                "region {:?} is not associated with any bound region from A!",
+                r0)
         }
     }
 
@@ -297,7 +296,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
 
             if a_r.is_some() && b_r.is_some() && only_new_vars {
                 // Related to exactly one bound variable from each fn:
-                return rev_lookup(infcx, span, a_map, a_r.unwrap());
+                return rev_lookup(span, a_map, a_r.unwrap());
             } else if a_r.is_none() && b_r.is_none() {
                 // Not related to bound variables from either fn:
                 assert!(!r0.is_bound());
@@ -308,8 +307,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
             }
         }
 
-        fn rev_lookup(infcx: &InferCtxt,
-                      span: Span,
+        fn rev_lookup(span: Span,
                       a_map: &FnvHashMap<ty::BoundRegion, ty::Region>,
                       r: ty::Region) -> ty::Region
         {
@@ -318,9 +316,10 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
                     return ty::ReLateBound(ty::DebruijnIndex::new(1), *a_br);
                 }
             }
-            infcx.tcx.sess.span_bug(
+            span_bug!(
                 span,
-                &format!("could not find original bound region for {:?}", r));
+                "could not find original bound region for {:?}",
+                r);
         }
 
         fn fresh_bound_variable(infcx: &InferCtxt, debruijn: ty::DebruijnIndex) -> ty::Region {
@@ -336,9 +335,10 @@ fn var_ids<'a, 'tcx>(fields: &CombineFields<'a, 'tcx>,
        .map(|(_, r)| match *r {
            ty::ReVar(r) => { r }
            r => {
-               fields.tcx().sess.span_bug(
+               span_bug!(
                    fields.trace.origin.span(),
-                   &format!("found non-region-vid: {:?}", r));
+                   "found non-region-vid: {:?}",
+                   r);
            }
        })
        .collect()
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 725c6d9593c..35e1be7e5f4 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -471,7 +471,7 @@ pub fn mk_eq_impl_headers<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
     match (a.trait_ref, b.trait_ref) {
         (Some(a_ref), Some(b_ref)) => mk_eq_trait_refs(cx, a_is_expected, origin, a_ref, b_ref),
         (None, None) => mk_eqty(cx, a_is_expected, origin, a.self_ty, b.self_ty),
-        _ => cx.tcx.sess.bug("mk_eq_impl_headers given mismatched impl kinds"),
+        _ => bug!("mk_eq_impl_headers given mismatched impl kinds"),
     }
 }
 
@@ -536,10 +536,10 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
     match drain_fulfillment_cx(infcx, fulfill_cx, result) {
         Ok(v) => v,
         Err(errors) => {
-            infcx.tcx.sess.span_bug(
+            span_bug!(
                 span,
-                &format!("Encountered errors `{:?}` fulfilling during trans",
-                         errors));
+                "Encountered errors `{:?}` fulfilling during trans",
+                errors);
         }
     }
 }
@@ -1114,9 +1114,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             None if self.errors_since_creation() =>
                 self.tcx.types.err,
             None => {
-                self.tcx.sess.bug(
-                    &format!("no type for node {}: {} in fcx",
-                            id, self.tcx.map.node_to_string(id)));
+                bug!("no type for node {}: {} in fcx",
+                     id, self.tcx.map.node_to_string(id));
             }
         }
     }
@@ -1125,7 +1124,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         match self.tables.borrow().node_types.get(&ex.id) {
             Some(&t) => t,
             None => {
-                self.tcx.sess.bug("no type for expr in fcx");
+                bug!("no type for expr in fcx");
             }
         }
     }
diff --git a/src/librustc/infer/region_inference/graphviz.rs b/src/librustc/infer/region_inference/graphviz.rs
index e561f4a3548..e611c005691 100644
--- a/src/librustc/infer/region_inference/graphviz.rs
+++ b/src/librustc/infer/region_inference/graphviz.rs
@@ -90,7 +90,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
         };
 
         if output_template.is_empty() {
-            tcx.sess.bug("empty string provided as RUST_REGION_GRAPH");
+            bug!("empty string provided as RUST_REGION_GRAPH");
         }
 
         if output_template.contains('%') {
@@ -182,13 +182,13 @@ impl<'a, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'tcx> {
     fn node_id(&self, n: &Node) -> dot::Id {
         let node_id = match self.node_ids.get(n) {
             Some(node_id) => node_id,
-            None => panic!("no node_id found for node: {:?}", n),
+            None => bug!("no node_id found for node: {:?}", n),
         };
         let name = || format!("node_{}", node_id);
         match dot::Id::new(name()) {
             Ok(id) => id,
             Err(_) => {
-                panic!("failed to create graphviz node identified by {}", name());
+                bug!("failed to create graphviz node identified by {}", name());
             }
         }
     }
diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs
index 2b74dcb40c4..2f610bf2380 100644
--- a/src/librustc/infer/region_inference/mod.rs
+++ b/src/librustc/infer/region_inference/mod.rs
@@ -309,7 +309,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         while undo_log.len() > snapshot.length + 1 {
             match undo_log.pop().unwrap() {
                 OpenSnapshot => {
-                    panic!("Failure to observe stack discipline");
+                    bug!("Failure to observe stack discipline");
                 }
                 CommitedSnapshot => {}
                 AddVar(vid) => {
@@ -413,7 +413,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         self.bound_count.set(sc + 1);
 
         if sc >= self.bound_count.get() {
-            self.tcx.sess.bug("rollover in RegionInference new_bound()");
+            bug!("rollover in RegionInference new_bound()");
         }
 
         ReLateBound(debruijn, BrFresh(sc))
@@ -497,10 +497,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             (ReLateBound(..), _) |
             (_, ReEarlyBound(..)) |
             (_, ReLateBound(..)) => {
-                self.tcx.sess.span_bug(origin.span(),
-                                       &format!("cannot relate bound region: {:?} <= {:?}",
-                                                sub,
-                                                sup));
+                span_bug!(origin.span(),
+                          "cannot relate bound region: {:?} <= {:?}",
+                          sub,
+                          sup);
             }
             (_, ReStatic) => {
                 // all regions are subregions of static, so we can ignore this
@@ -570,9 +570,9 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
     pub fn resolve_var(&self, rid: RegionVid) -> ty::Region {
         match *self.values.borrow() {
             None => {
-                self.tcx.sess.span_bug((*self.var_origins.borrow())[rid.index as usize].span(),
-                                       "attempt to resolve region variable before values have \
-                                        been computed!")
+                span_bug!((*self.var_origins.borrow())[rid.index as usize].span(),
+                          "attempt to resolve region variable before values have \
+                           been computed!")
             }
             Some(ref values) => {
                 let r = lookup(values, rid);
@@ -733,7 +733,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             (_, ReLateBound(..)) |
             (ReEarlyBound(..), _) |
             (_, ReEarlyBound(..)) => {
-                self.tcx.sess.bug(&format!("cannot relate bound region: LUB({:?}, {:?})", a, b));
+                bug!("cannot relate bound region: LUB({:?}, {:?})", a, b);
             }
 
             (ReStatic, _) | (_, ReStatic) => {
@@ -745,11 +745,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             }
 
             (ReVar(v_id), _) | (_, ReVar(v_id)) => {
-                self.tcx.sess.span_bug((*self.var_origins.borrow())[v_id.index as usize].span(),
-                                       &format!("lub_concrete_regions invoked with non-concrete \
-                                                 regions: {:?}, {:?}",
-                                                a,
-                                                b));
+                span_bug!((*self.var_origins.borrow())[v_id.index as usize].span(),
+                          "lub_concrete_regions invoked with non-concrete \
+                           regions: {:?}, {:?}",
+                          a,
+                          b);
             }
 
             (ReFree(ref fr), ReScope(s_id)) |
@@ -1193,13 +1193,13 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
             }
         }
 
-        self.tcx.sess.span_bug((*self.var_origins.borrow())[node_idx.index as usize].span(),
-                               &format!("collect_error_for_expanding_node() could not find \
-                                         error for var {:?}, lower_bounds={:?}, \
-                                         upper_bounds={:?}",
-                                        node_idx,
-                                        lower_bounds,
-                                        upper_bounds));
+        span_bug!((*self.var_origins.borrow())[node_idx.index as usize].span(),
+                  "collect_error_for_expanding_node() could not find \
+                   error for var {:?}, lower_bounds={:?}, \
+                   upper_bounds={:?}",
+                  node_idx,
+                  lower_bounds,
+                  upper_bounds);
     }
 
     fn collect_concrete_regions(&self,
diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs
index c54843410ad..8651b52e3fe 100644
--- a/src/librustc/infer/resolve.rs
+++ b/src/librustc/infer/resolve.rs
@@ -127,9 +127,7 @@ impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
                     self.tcx().types.err
                 }
                 ty::TyInfer(_) => {
-                    self.infcx.tcx.sess.bug(
-                        &format!("Unexpected type in full type resolver: {:?}",
-                                t));
+                    bug!("Unexpected type in full type resolver: {:?}", t);
                 }
                 _ => {
                     t.super_fold_with(self)
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index c8da346085d..3cc076f1f00 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -159,8 +159,8 @@ impl<'tcx> TypeVariableTable<'tcx> {
 
         let (relations, default) = match old_value {
             Bounded { relations, default } => (relations, default),
-            Known(_) => panic!("Asked to instantiate variable that is \
-                               already instantiated")
+            Known(_) => bug!("Asked to instantiate variable that is \
+                              already instantiated")
         };
 
         for &(dir, vid) in &relations {
@@ -259,7 +259,7 @@ impl<'tcx> TypeVariableTable<'tcx> {
                         // quick check to see if this variable was
                         // created since the snapshot started or not.
                         let escaping_type = match self.values.get(vid.index as usize).value {
-                            Bounded { .. } => unreachable!(),
+                            Bounded { .. } => bug!(),
                             Known(ty) => ty,
                         };
                         escaping_types.push(escaping_type);
@@ -318,7 +318,7 @@ impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> {
 
 fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
     match v.value {
-        Known(_) => panic!("var_sub_var: variable is known"),
+        Known(_) => bug!("var_sub_var: variable is known"),
         Bounded { ref mut relations, .. } => relations
     }
 }
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index 8224422d45c..e78ff513ac4 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -183,7 +183,7 @@ impl LintStore {
                     // We load builtin lints first, so a duplicate is a compiler bug.
                     // Use early_error when handling -W help with no crate.
                     (None, _) => early_error(config::ErrorOutputType::default(), &msg[..]),
-                    (Some(sess), false) => sess.bug(&msg[..]),
+                    (Some(_), false) => bug!("{}", msg),
 
                     // A duplicate name from a plugin is a user error.
                     (Some(sess), true)  => sess.err(&msg[..]),
@@ -221,7 +221,7 @@ impl LintStore {
                 // We load builtin lints first, so a duplicate is a compiler bug.
                 // Use early_error when handling -W help with no crate.
                 (None, _) => early_error(config::ErrorOutputType::default(), &msg[..]),
-                (Some(sess), false) => sess.bug(&msg[..]),
+                (Some(_), false) => bug!("{}", msg),
 
                 // A duplicate name from a plugin is a user error.
                 (Some(sess), true)  => sess.err(&msg[..]),
@@ -232,7 +232,7 @@ impl LintStore {
     pub fn register_renamed(&mut self, old_name: &str, new_name: &str) {
         let target = match self.by_name.get(new_name) {
             Some(&Id(lint_id)) => lint_id.clone(),
-            _ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
+            _ => bug!("invalid lint renaming of {} to {}", old_name, new_name)
         };
         self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
     }
@@ -430,7 +430,7 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
             format!("{} [-{} {}]", msg,
                     match level {
                         Warn => 'W', Deny => 'D', Forbid => 'F',
-                        Allow => panic!()
+                        Allow => bug!()
                     }, name.replace("_", "-"))
         },
         Node(src) => {
@@ -447,7 +447,7 @@ pub fn raw_struct_lint<'a>(sess: &'a Session,
         (Warn, None)     => sess.struct_warn(&msg[..]),
         (Deny, Some(sp)) => sess.struct_span_err(sp, &msg[..]),
         (Deny, None)     => sess.struct_err(&msg[..]),
-        _ => sess.bug("impossible level in raw_emit_lint"),
+        _ => bug!("impossible level in raw_emit_lint"),
     };
 
     // Check for future incompatibility lints and issue a stronger warning.
@@ -1275,9 +1275,9 @@ pub fn check_crate(tcx: &TyCtxt, access_levels: &AccessLevels) {
     // in the iteration code.
     for (id, v) in tcx.sess.lints.borrow().iter() {
         for &(lint, span, ref msg) in v {
-            tcx.sess.span_bug(span,
-                              &format!("unprocessed lint {} at {}: {}",
-                                       lint.as_str(), tcx.map.node_to_string(*id), *msg))
+            span_bug!(span,
+                      "unprocessed lint {} at {}: {}",
+                      lint.as_str(), tcx.map.node_to_string(*id), *msg)
         }
     }
 
@@ -1314,9 +1314,7 @@ pub fn check_ast_crate(sess: &Session, krate: &ast::Crate) {
     // in the iteration code.
     for (_, v) in sess.lints.borrow().iter() {
         for &(lint, span, ref msg) in v {
-            sess.span_bug(span,
-                          &format!("unprocessed lint {}: {}",
-                                   lint.as_str(), *msg))
+            span_bug!(span, "unprocessed lint {}: {}", lint.as_str(), *msg)
         }
     }
 }
diff --git a/src/librustc/macros.rs b/src/librustc/macros.rs
index ed764ebd9f9..76dca1bb5b6 100644
--- a/src/librustc/macros.rs
+++ b/src/librustc/macros.rs
@@ -44,3 +44,18 @@ macro_rules! enum_from_u32 {
         }
     }
 }
+
+#[macro_export]
+macro_rules! bug {
+    () => ( bug!("impossible case reached") );
+    ($($message:tt)*) => ({
+        $crate::session::bug_fmt(file!(), line!(), format_args!($($message)*))
+    })
+}
+
+#[macro_export]
+macro_rules! span_bug {
+    ($span:expr, $($message:tt)*) => ({
+        $crate::session::span_bug_fmt(file!(), line!(), $span, format_args!($($message)*))
+    })
+}
diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs
index a6907aad297..b86d74545cb 100644
--- a/src/librustc/middle/astconv_util.rs
+++ b/src/librustc/middle/astconv_util.rs
@@ -67,8 +67,7 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &TyCtxt<'tcx>, ast_ty: &ast::Ty)
     if let ast::TyPath(None, ref path) = ast_ty.node {
         let def = match tcx.def_map.borrow().get(&ast_ty.id) {
             None => {
-                tcx.sess.span_bug(ast_ty.span,
-                                  &format!("unbound path {:?}", path))
+                span_bug!(ast_ty.span, "unbound path {:?}", path)
             }
             Some(d) => d.full_def()
         };
diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs
index e708950c69e..4efb40abdb0 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -309,7 +309,7 @@ pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
     {
         let mut say = |s: &str| {
             match (sp, sess) {
-                (_, None) => panic!("{}", s),
+                (_, None) => bug!("{}", s),
                 (Some(sp), Some(sess)) => sess.span_err(sp, s),
                 (None, Some(sess)) => sess.err(s),
             }
@@ -336,121 +336,123 @@ pub struct DummyCrateStore;
 #[allow(unused_variables)]
 impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     // item info
-    fn stability(&self, def: DefId) -> Option<attr::Stability> { unimplemented!() }
-    fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { unimplemented!() }
-    fn visibility(&self, def: DefId) -> hir::Visibility { unimplemented!() }
+    fn stability(&self, def: DefId) -> Option<attr::Stability> { bug!("stability") }
+    fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { bug!("deprecation") }
+    fn visibility(&self, def: DefId) -> hir::Visibility { bug!("visibility") }
     fn closure_kind(&self, tcx: &TyCtxt<'tcx>, def_id: DefId)
-                    -> ty::ClosureKind  { unimplemented!() }
+                    -> ty::ClosureKind  { bug!("closure_kind") }
     fn closure_ty(&self, tcx: &TyCtxt<'tcx>, def_id: DefId)
-                  -> ty::ClosureTy<'tcx>  { unimplemented!() }
-    fn item_variances(&self, def: DefId) -> ty::ItemVariances { unimplemented!() }
-    fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { unimplemented!() }
+                  -> ty::ClosureTy<'tcx>  { bug!("closure_ty") }
+    fn item_variances(&self, def: DefId) -> ty::ItemVariances { bug!("item_variances") }
+    fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { bug!("repr_attrs") }
     fn item_type(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-                 -> ty::TypeScheme<'tcx> { unimplemented!() }
-    fn relative_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
+                 -> ty::TypeScheme<'tcx> { bug!("item_type") }
+    fn relative_item_path(&self, def: DefId)
+                          -> Vec<hir_map::PathElem> { bug!("relative_item_path") }
     fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
-        unimplemented!()
+        bug!("visible_parent_map")
     }
-    fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { unimplemented!() }
-    fn item_name(&self, def: DefId) -> ast::Name { unimplemented!() }
+    fn extern_item_path(&self, def: DefId) -> Vec<hir_map::PathElem> { bug!("extern_item_path") }
+    fn item_name(&self, def: DefId) -> ast::Name { bug!("item_name") }
     fn item_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-                       -> ty::GenericPredicates<'tcx> { unimplemented!() }
+                       -> ty::GenericPredicates<'tcx> { bug!("item_predicates") }
     fn item_super_predicates(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-                             -> ty::GenericPredicates<'tcx> { unimplemented!() }
-    fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { unimplemented!() }
-    fn item_symbol(&self, def: DefId) -> String { unimplemented!() }
+                             -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
+    fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
+    fn item_symbol(&self, def: DefId) -> String { bug!("item_symbol") }
     fn trait_def(&self, tcx: &TyCtxt<'tcx>, def: DefId)-> ty::TraitDef<'tcx>
-        { unimplemented!() }
+        { bug!("trait_def") }
     fn adt_def(&self, tcx: &TyCtxt<'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>
-        { unimplemented!() }
-    fn method_arg_names(&self, did: DefId) -> Vec<String> { unimplemented!() }
+        { bug!("adt_def") }
+    fn method_arg_names(&self, did: DefId) -> Vec<String> { bug!("method_arg_names") }
     fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId> { vec![] }
 
     // trait info
     fn implementations_of_trait(&self, def_id: DefId) -> Vec<DefId> { vec![] }
     fn provided_trait_methods(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-                              -> Vec<Rc<ty::Method<'tcx>>> { unimplemented!() }
+                              -> Vec<Rc<ty::Method<'tcx>>> { bug!("provided_trait_methods") }
     fn trait_item_def_ids(&self, def: DefId)
-                          -> Vec<ty::ImplOrTraitItemId> { unimplemented!() }
+                          -> Vec<ty::ImplOrTraitItemId> { bug!("trait_item_def_ids") }
 
     // impl info
     fn impl_items(&self, impl_def_id: DefId) -> Vec<ty::ImplOrTraitItemId>
-        { unimplemented!() }
+        { bug!("impl_items") }
     fn impl_trait_ref(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-                      -> Option<ty::TraitRef<'tcx>> { unimplemented!() }
-    fn impl_polarity(&self, def: DefId) -> Option<hir::ImplPolarity> { unimplemented!() }
+                      -> Option<ty::TraitRef<'tcx>> { bug!("impl_trait_ref") }
+    fn impl_polarity(&self, def: DefId) -> Option<hir::ImplPolarity> { bug!("impl_polarity") }
     fn custom_coerce_unsized_kind(&self, def: DefId)
                                   -> Option<ty::adjustment::CustomCoerceUnsized>
-        { unimplemented!() }
+        { bug!("custom_coerce_unsized_kind") }
     fn associated_consts(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-                         -> Vec<Rc<ty::AssociatedConst<'tcx>>> { unimplemented!() }
-    fn impl_parent(&self, def: DefId) -> Option<DefId> { unimplemented!() }
+                         -> Vec<Rc<ty::AssociatedConst<'tcx>>> { bug!("associated_consts") }
+    fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
 
     // trait/impl-item info
     fn trait_of_item(&self, tcx: &TyCtxt<'tcx>, def_id: DefId)
-                     -> Option<DefId> { unimplemented!() }
+                     -> Option<DefId> { bug!("trait_of_item") }
     fn impl_or_trait_item(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-                          -> Option<ty::ImplOrTraitItem<'tcx>> { unimplemented!() }
+                          -> Option<ty::ImplOrTraitItem<'tcx>> { bug!("impl_or_trait_item") }
 
     // flags
-    fn is_const_fn(&self, did: DefId) -> bool { unimplemented!() }
-    fn is_defaulted_trait(&self, did: DefId) -> bool { unimplemented!() }
-    fn is_impl(&self, did: DefId) -> bool { unimplemented!() }
-    fn is_default_impl(&self, impl_did: DefId) -> bool { unimplemented!() }
-    fn is_extern_item(&self, tcx: &TyCtxt<'tcx>, did: DefId) -> bool { unimplemented!() }
-    fn is_static_method(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_const_fn(&self, did: DefId) -> bool { bug!("is_const_fn") }
+    fn is_defaulted_trait(&self, did: DefId) -> bool { bug!("is_defaulted_trait") }
+    fn is_impl(&self, did: DefId) -> bool { bug!("is_impl") }
+    fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
+    fn is_extern_item(&self, tcx: &TyCtxt<'tcx>, did: DefId) -> bool { bug!("is_extern_item") }
+    fn is_static_method(&self, did: DefId) -> bool { bug!("is_static_method") }
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false }
-    fn is_typedef(&self, did: DefId) -> bool { unimplemented!() }
+    fn is_typedef(&self, did: DefId) -> bool { bug!("is_typedef") }
 
     // crate metadata
     fn dylib_dependency_formats(&self, cnum: ast::CrateNum)
                                     -> Vec<(ast::CrateNum, LinkagePreference)>
-        { unimplemented!() }
+        { bug!("dylib_dependency_formats") }
     fn lang_items(&self, cnum: ast::CrateNum) -> Vec<(DefIndex, usize)>
-        { unimplemented!() }
+        { bug!("lang_items") }
     fn missing_lang_items(&self, cnum: ast::CrateNum) -> Vec<lang_items::LangItem>
-        { unimplemented!() }
-    fn is_staged_api(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
-    fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
-    fn is_allocator(&self, cnum: ast::CrateNum) -> bool { unimplemented!() }
-    fn extern_crate(&self, cnum: ast::CrateNum) -> Option<ExternCrate> { unimplemented!() }
+        { bug!("missing_lang_items") }
+    fn is_staged_api(&self, cnum: ast::CrateNum) -> bool { bug!("is_staged_api") }
+    fn is_explicitly_linked(&self, cnum: ast::CrateNum) -> bool { bug!("is_explicitly_linked") }
+    fn is_allocator(&self, cnum: ast::CrateNum) -> bool { bug!("is_allocator") }
+    fn extern_crate(&self, cnum: ast::CrateNum) -> Option<ExternCrate> { bug!("extern_crate") }
     fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec<ast::Attribute>
-        { unimplemented!() }
-    fn crate_name(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() }
+        { bug!("crate_attrs") }
+    fn crate_name(&self, cnum: ast::CrateNum) -> InternedString { bug!("crate_name") }
     fn original_crate_name(&self, cnum: ast::CrateNum) -> InternedString {
-        unimplemented!()
+        bug!("original_crate_name")
     }
-    fn crate_hash(&self, cnum: ast::CrateNum) -> Svh { unimplemented!() }
-    fn crate_disambiguator(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() }
+    fn crate_hash(&self, cnum: ast::CrateNum) -> Svh { bug!("crate_hash") }
+    fn crate_disambiguator(&self, cnum: ast::CrateNum)
+                           -> InternedString { bug!("crate_disambiguator") }
     fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
                                 -> FnvHashMap<DefId, Vec<ast::Attribute>>
-        { unimplemented!() }
+        { bug!("crate_struct_field_attrs") }
     fn plugin_registrar_fn(&self, cnum: ast::CrateNum) -> Option<DefId>
-        { unimplemented!() }
+        { bug!("plugin_registrar_fn") }
     fn native_libraries(&self, cnum: ast::CrateNum) -> Vec<(NativeLibraryKind, String)>
-        { unimplemented!() }
-    fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId> { unimplemented!() }
+        { bug!("native_libraries") }
+    fn reachable_ids(&self, cnum: ast::CrateNum) -> Vec<DefId> { bug!("reachable_ids") }
 
     // resolve
-    fn def_key(&self, def: DefId) -> hir_map::DefKey { unimplemented!() }
-    fn relative_def_path(&self, def: DefId) -> hir_map::DefPath { unimplemented!() }
-    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> { unimplemented!() }
+    fn def_key(&self, def: DefId) -> hir_map::DefKey { bug!("def_key") }
+    fn relative_def_path(&self, def: DefId) -> hir_map::DefPath { bug!("relative_def_path") }
+    fn variant_kind(&self, def_id: DefId) -> Option<VariantKind> { bug!("variant_kind") }
     fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option<DefId>
-        { unimplemented!() }
+        { bug!("struct_ctor_def_id") }
     fn tuple_struct_definition_if_ctor(&self, did: DefId) -> Option<DefId>
-        { unimplemented!() }
-    fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { unimplemented!() }
-    fn item_children(&self, did: DefId) -> Vec<ChildItem> { unimplemented!() }
+        { bug!("tuple_struct_definition_if_ctor") }
+    fn struct_field_names(&self, def: DefId) -> Vec<ast::Name> { bug!("struct_field_names") }
+    fn item_children(&self, did: DefId) -> Vec<ChildItem> { bug!("item_children") }
     fn crate_top_level_items(&self, cnum: ast::CrateNum) -> Vec<ChildItem>
-        { unimplemented!() }
+        { bug!("crate_top_level_items") }
 
     // misc. metadata
     fn maybe_get_item_ast(&'tcx self, tcx: &TyCtxt<'tcx>, def: DefId)
-                          -> FoundAst<'tcx> { unimplemented!() }
+                          -> FoundAst<'tcx> { bug!("maybe_get_item_ast") }
     fn maybe_get_item_mir(&self, tcx: &TyCtxt<'tcx>, def: DefId)
-                          -> Option<Mir<'tcx>> { unimplemented!() }
+                          -> Option<Mir<'tcx>> { bug!("maybe_get_item_mir") }
     fn is_item_mir_available(&self, def: DefId) -> bool {
-        unimplemented!()
+        bug!("is_item_mir_available")
     }
 
     // This is basically a 1-based range of ints, which is a little
@@ -460,18 +462,18 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     fn used_link_args(&self) -> Vec<String> { vec![] }
 
     // utility functions
-    fn metadata_filename(&self) -> &str { unimplemented!() }
-    fn metadata_section_name(&self, target: &Target) -> &str { unimplemented!() }
+    fn metadata_filename(&self) -> &str { bug!("metadata_filename") }
+    fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") }
     fn encode_type(&self,
                    tcx: &TyCtxt<'tcx>,
                    ty: Ty<'tcx>,
                    def_id_to_string: fn(&TyCtxt<'tcx>, DefId) -> String)
                    -> Vec<u8> {
-        unimplemented!()
+        bug!("encode_type")
     }
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(ast::CrateNum, Option<PathBuf>)>
         { vec![] }
-    fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource { unimplemented!() }
+    fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource { bug!("used_crate_source") }
     fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<ast::CrateNum> { None }
     fn encode_metadata(&self,
                        tcx: &TyCtxt<'tcx>,
@@ -481,7 +483,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
                        reachable: &NodeSet,
                        mir_map: &MirMap<'tcx>,
                        krate: &hir::Crate) -> Vec<u8> { vec![] }
-    fn metadata_encoding_version(&self) -> &[u8] { unimplemented!() }
+    fn metadata_encoding_version(&self) -> &[u8] { bug!("metadata_encoding_version") }
 }
 
 
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index 2b8ed14701d..18bea745858 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -125,7 +125,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         if let ty::TyStruct(def, _) = self.tcx.expr_ty_adjusted(lhs).sty {
             self.insert_def_id(def.struct_variant().field_named(name).did);
         } else {
-            self.tcx.sess.span_bug(lhs.span, "named field access on non-struct")
+            span_bug!(lhs.span, "named field access on non-struct")
         }
     }
 
@@ -141,7 +141,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         let pat_ty = self.tcx.node_id_to_type(lhs.id);
         let variant = match pat_ty.sty {
             ty::TyStruct(adt, _) | ty::TyEnum(adt, _) => adt.variant_of_def(def),
-            _ => self.tcx.sess.span_bug(lhs.span, "non-ADT in struct pattern")
+            _ => span_bug!(lhs.span, "non-ADT in struct pattern")
         };
         for pat in pats {
             if let PatKind::Wild = pat.node.pat.node {
diff --git a/src/librustc/middle/def.rs b/src/librustc/middle/def.rs
index 6cbcd41d84a..e6ea000936c 100644
--- a/src/librustc/middle/def.rs
+++ b/src/librustc/middle/def.rs
@@ -71,7 +71,7 @@ impl PathResolution {
     /// Get the definition, if fully resolved, otherwise panic.
     pub fn full_def(&self) -> Def {
         if self.depth != 0 {
-            panic!("path not fully resolved: {:?}", self);
+            bug!("path not fully resolved: {:?}", self);
         }
         self.base_def
     }
@@ -116,7 +116,7 @@ impl Def {
             Def::TyParam(..) | Def::Struct(..) | Def::Trait(..) |
             Def::Method(..) | Def::Const(..) | Def::AssociatedConst(..) |
             Def::PrimTy(..) | Def::Label(..) | Def::SelfTy(..) | Def::Err => {
-                panic!("attempted .var_id() on invalid {:?}", self)
+                bug!("attempted .var_id() on invalid {:?}", self)
             }
         }
     }
@@ -135,7 +135,7 @@ impl Def {
             Def::PrimTy(..) |
             Def::SelfTy(..) |
             Def::Err => {
-                panic!("attempted .def_id() on invalid def: {:?}", self)
+                bug!("attempted .def_id() on invalid def: {:?}", self)
             }
         }
     }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 744022d1d5e..bfc96005bc8 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -224,7 +224,7 @@ impl OverloadedCallType {
             }
         }
 
-        tcx.sess.bug("overloaded call didn't map to known function trait")
+        bug!("overloaded call didn't map to known function trait")
     }
 
     fn from_method_id(tcx: &TyCtxt, method_id: DefId)
@@ -564,9 +564,10 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                             OverloadedCallType::from_method_id(self.tcx(), method_id)
                         }
                         None => {
-                            self.tcx().sess.span_bug(
+                            span_bug!(
                                 callee.span,
-                                &format!("unexpected callee type {}", callee_ty))
+                                "unexpected callee type {}",
+                                callee_ty)
                         }
                     };
                 match overloaded_call_type {
@@ -683,7 +684,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
             // may not. This will generate an error earlier in typeck,
             // so we can just ignore it.
             if !self.tcx().sess.has_errors() {
-                self.tcx().sess.span_bug(
+                span_bug!(
                     with_expr.span,
                     "with expression doesn't evaluate to a struct");
             }
@@ -750,9 +751,9 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
 
                     let (m, r) = match self_ty.sty {
                         ty::TyRef(r, ref m) => (m.mutbl, r),
-                        _ => self.tcx().sess.span_bug(expr.span,
-                                &format!("bad overloaded deref type {:?}",
-                                    method_ty))
+                        _ => span_bug!(expr.span,
+                                "bad overloaded deref type {:?}",
+                                method_ty)
                     };
                     let bk = ty::BorrowKind::from_mutbl(m);
                     self.delegate.borrow(expr.id, expr.span, cmt,
@@ -934,7 +935,6 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr,
                pat);
         return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
-            let tcx = self.tcx();
             let def_map = &self.tcx().def_map;
             if pat_util::pat_is_binding(&def_map.borrow(), pat) {
                 match pat.node {
@@ -947,7 +947,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                         }
                     }
                     _ => {
-                        tcx.sess.span_bug(
+                        span_bug!(
                             pat.span,
                             "binding pattern not an identifier");
                     }
@@ -972,8 +972,6 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         let delegate = &mut self.delegate;
         return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
             if pat_util::pat_is_binding(&def_map.borrow(), pat) {
-                let tcx = typer.tcx;
-
                 debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
                        cmt_pat,
                        pat,
@@ -1007,7 +1005,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                         delegate.consume_pat(pat, cmt_pat, mode);
                     }
                     _ => {
-                        tcx.sess.span_bug(
+                        span_bug!(
                             pat.span,
                             "binding pattern not an identifier");
                     }
@@ -1117,10 +1115,10 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                             // reported.
 
                             if !tcx.sess.has_errors() {
-                                let msg = format!("Pattern has unexpected def: {:?} and type {:?}",
-                                                  def,
-                                                  cmt_pat.ty);
-                                tcx.sess.span_bug(pat.span, &msg[..])
+                                span_bug!(pat.span,
+                                          "Pattern has unexpected def: {:?} and type {:?}",
+                                          def,
+                                          cmt_pat.ty);
                             }
                         }
                     }
diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs
index 20f2c5ad43f..ae0540696c5 100644
--- a/src/librustc/middle/free_region.rs
+++ b/src/librustc/middle/free_region.rs
@@ -49,7 +49,7 @@ impl FreeRegionMap {
     }
 
     pub fn relate_free_regions_from_predicates<'tcx>(&mut self,
-                                                     tcx: &TyCtxt<'tcx>,
+                                                     _tcx: &TyCtxt<'tcx>,
                                                      predicates: &[ty::Predicate<'tcx>]) {
         debug!("relate_free_regions_from_predicates(predicates={:?})", predicates);
         for predicate in predicates {
@@ -72,10 +72,9 @@ impl FreeRegionMap {
                         }
                         _ => {
                             // All named regions are instantiated with free regions.
-                            tcx.sess.bug(
-                                &format!("record_region_bounds: non free region: {:?} / {:?}",
-                                         r_a,
-                                         r_b));
+                            bug!("record_region_bounds: non free region: {:?} / {:?}",
+                                 r_a,
+                                 r_b);
                         }
                     }
                 }
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index 939ea91cdd4..fd74ccac975 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -66,7 +66,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
         let param_env = match self.param_envs.last() {
             Some(p) => p,
             None => {
-                self.tcx.sess.span_bug(
+                span_bug!(
                     span,
                     "transmute encountered outside of any fn");
             }
@@ -245,9 +245,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
                             }
                         }
                         _ => {
-                            self.tcx
-                                .sess
-                                .span_bug(expr.span, "transmute wasn't a bare fn?!");
+                            span_bug!(expr.span, "transmute wasn't a bare fn?!");
                         }
                     }
                 }
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index f6eedb49e24..cc37ee7dbda 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -325,13 +325,10 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> {
 
     fn variable(&self, node_id: NodeId, span: Span) -> Variable {
         match self.variable_map.get(&node_id) {
-          Some(&var) => var,
-          None => {
-            self.tcx
-                .sess
-                .span_bug(span, &format!("no variable registered for id {}",
-                                        node_id));
-          }
+            Some(&var) => var,
+            None => {
+                span_bug!(span, "no variable registered for id {}", node_id);
+            }
         }
     }
 
@@ -578,10 +575,10 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             // above and the propagation code below; the two sets of
             // code have to agree about which AST nodes are worth
             // creating liveness nodes for.
-            self.ir.tcx.sess.span_bug(
+            span_bug!(
                 span,
-                &format!("no live node registered for node {}",
-                        node_id));
+                "no live node registered for node {}",
+                node_id);
           }
         }
     }
@@ -703,15 +700,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 // to find with one
                 match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
                     Some(Def::Label(loop_id)) => loop_id,
-                    _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \
-                                                        doesn't refer to a loop")
+                    _ => span_bug!(sp, "label on break/loop \
+                                        doesn't refer to a loop")
                 }
             }
             None => {
                 // Vanilla 'break' or 'loop', so use the enclosing
                 // loop scope
                 if self.loop_scope.is_empty() {
-                    self.ir.tcx.sess.span_bug(sp, "break outside loop");
+                    span_bug!(sp, "break outside loop");
                 } else {
                     *self.loop_scope.last().unwrap()
                 }
@@ -967,7 +964,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                  let caps = match this.ir.capture_info_map.get(&expr.id) {
                     Some(caps) => caps.clone(),
                     None => {
-                        this.ir.tcx.sess.span_bug(expr.span, "no registered caps");
+                        span_bug!(expr.span, "no registered caps");
                      }
                  };
                  caps.iter().rev().fold(succ, |succ, cap| {
@@ -1061,8 +1058,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
               match self.break_ln.get(&sc) {
                   Some(&b) => b,
-                  None => self.ir.tcx.sess.span_bug(expr.span,
-                                                    "break to unknown label")
+                  None => span_bug!(expr.span, "break to unknown label")
               }
           }
 
@@ -1075,8 +1071,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
               match self.cont_ln.get(&sc) {
                   Some(&b) => b,
-                  None => self.ir.tcx.sess.span_bug(expr.span,
-                                                    "loop to unknown label")
+                  None => span_bug!(expr.span, "loop to unknown label")
               }
           }
 
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 6328f920cb7..ef031ad13f1 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -312,9 +312,9 @@ impl MutabilityCategory {
                         McImmutable
                     }
                 }
-                _ => tcx.sess.span_bug(p.span, "expected identifier pattern")
+                _ => span_bug!(p.span, "expected identifier pattern")
             },
-            _ => tcx.sess.span_bug(tcx.map.span(id), "expected identifier pattern")
+            _ => span_bug!(tcx.map.span(id), "expected identifier pattern")
         };
         debug!("MutabilityCategory::{}(tcx, id={:?}) => {:?}",
                "from_local", id, ret);
@@ -559,8 +559,8 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
           Def::TyParam(..) |
           Def::Label(_) | Def::SelfTy(..) |
           Def::AssociatedTy(..) => {
-              self.tcx().sess.span_bug(span, &format!("Unexpected definition in \
-                                                       memory categorization: {:?}", def));
+              span_bug!(span, "Unexpected definition in \
+                               memory categorization: {:?}", def);
           }
 
           Def::Static(_, mutbl) => {
@@ -583,18 +583,19 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
                               self.cat_upvar(id, span, var_id, fn_node_id, kind)
                           }
                           None => {
-                              self.tcx().sess.span_bug(
+                              span_bug!(
                                   span,
-                                  &format!("No closure kind for {:?}", closure_id));
+                                  "No closure kind for {:?}",
+                                  closure_id);
                           }
                       }
                   }
                   _ => {
-                      self.tcx().sess.span_bug(
+                      span_bug!(
                           span,
-                          &format!("Upvar of non-closure {} - {:?}",
-                                  fn_node_id,
-                                  ty));
+                          "Upvar of non-closure {} - {:?}",
+                          fn_node_id,
+                          ty);
                   }
               }
           }
@@ -610,7 +611,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             }))
           }
 
-          Def::Err => panic!("Def::Err in memory categorization")
+          Def::Err => bug!("Def::Err in memory categorization")
         }
     }
 
@@ -723,12 +724,12 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         let fn_body_id = {
             let fn_expr = match self.tcx().map.find(upvar_id.closure_expr_id) {
                 Some(ast_map::NodeExpr(e)) => e,
-                _ => unreachable!()
+                _ => bug!()
             };
 
             match fn_expr.node {
                 hir::ExprClosure(_, _, ref body) => body.id,
-                _ => unreachable!()
+                _ => bug!()
             }
         };
 
@@ -926,7 +927,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
                 let ptr = if implicit {
                     match ptr {
                         BorrowedPtr(bk, r) => Implicit(bk, r),
-                        _ => self.tcx().sess.span_bug(node.span(),
+                        _ => span_bug!(node.span(),
                             "Implicit deref of non-borrowed pointer")
                     }
                 } else {
@@ -1044,7 +1045,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
                     mutbl:m,
                     ty: match base_cmt.ty.builtin_deref(false, ty::NoPreference) {
                         Some(mt) => mt.ty,
-                        None => self.tcx().sess.bug("Found non-derefable type")
+                        None => bug!("Found non-derefable type")
                     },
                     note: NoteNone
                 })
@@ -1092,8 +1093,8 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
                 },
 
                 _ => {
-                    tcx.sess.span_bug(pat.span,
-                                      "type of slice pattern is not a slice");
+                    span_bug!(pat.span,
+                              "type of slice pattern is not a slice");
                 }
             }
         }
@@ -1261,9 +1262,10 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
                     }
                 }
                 _ => {
-                    self.tcx().sess.span_bug(
+                    span_bug!(
                         pat.span,
-                        &format!("enum pattern didn't resolve to enum or struct {:?}", opt_def));
+                        "enum pattern didn't resolve to enum or struct {:?}",
+                        opt_def);
                 }
             }
           }
@@ -1451,10 +1453,10 @@ impl<'tcx> cmt_<'tcx> {
                         match inner.cat {
                             Categorization::Deref(ref inner, _, _) => inner.clone(),
                             Categorization::Upvar(..) => inner.clone(),
-                            _ => unreachable!()
+                            _ => bug!()
                         }
                     }
-                    _ => unreachable!()
+                    _ => bug!()
                 })
             }
             NoteNone => None
@@ -1483,7 +1485,7 @@ impl<'tcx> cmt_<'tcx> {
                     Some(&Categorization::Upvar(ref var)) => {
                         var.to_string()
                     }
-                    Some(_) => unreachable!(),
+                    Some(_) => bug!(),
                     None => {
                         match pk {
                             Implicit(..) => {
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index 2e01a7fc249..149e895717c 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -67,10 +67,10 @@ fn method_might_be_inlined(tcx: &TyCtxt, sig: &hir::MethodSig,
             Some(ast_map::NodeItem(item)) =>
                 item_might_be_inlined(&item),
             Some(..) | None =>
-                tcx.sess.span_bug(impl_item.span, "impl did is not an item")
+                span_bug!(impl_item.span, "impl did is not an item")
         }
     } else {
-        tcx.sess.span_bug(impl_item.span, "found a foreign impl as a parent of a local method")
+        span_bug!(impl_item.span, "found a foreign impl as a parent of a local method")
     }
 }
 
@@ -94,8 +94,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
                 let def = match self.tcx.def_map.borrow().get(&expr.id) {
                     Some(d) => d.full_def(),
                     None => {
-                        self.tcx.sess.span_bug(expr.span,
-                                               "def ID not in def map?!")
+                        span_bug!(expr.span, "def ID not in def map?!")
                     }
                 };
 
@@ -312,12 +311,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
             ast_map::NodeVariant(_) |
             ast_map::NodeStructCtor(_) => {}
             _ => {
-                self.tcx
-                    .sess
-                    .bug(&format!("found unexpected thingy in worklist: {}",
-                                 self.tcx
-                                     .map
-                                     .node_to_string(search_item)))
+                bug!("found unexpected thingy in worklist: {}",
+                     self.tcx.map.node_to_string(search_item))
             }
         }
     }
diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs
index 1d1d05ea79f..2cde6ce9320 100644
--- a/src/librustc/middle/region.rs
+++ b/src/librustc/middle/region.rs
@@ -343,7 +343,7 @@ impl RegionMaps {
     pub fn lookup_code_extent(&self, e: CodeExtentData) -> CodeExtent {
         match self.code_extent_interner.borrow().get(&e) {
             Some(&d) => d,
-            None => panic!("unknown code extent {:?}", e)
+            None => bug!("unknown code extent {:?}", e)
         }
     }
     pub fn node_extent(&self, n: ast::NodeId) -> CodeExtent {
@@ -385,8 +385,8 @@ impl RegionMaps {
             }
             Entry::Vacant(v) => {
                 if self.code_extents.borrow().len() > 0xffffffffusize {
-                    unreachable!() // should pass a sess,
-                                   // but this isn't the only place
+                    bug!() // should pass a sess,
+                           // but this isn't the only place
                 }
                 let idx = CodeExtent(self.code_extents.borrow().len() as u32);
                 info!("CodeExtent({}) = {:?} [parent={}]", idx.0, e, parent.0);
@@ -470,7 +470,7 @@ impl RegionMaps {
     pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent {
         match self.var_map.borrow().get(&var_id) {
             Some(&r) => r,
-            None => { panic!("no enclosing scope for id {:?}", var_id); }
+            None => { bug!("no enclosing scope for id {:?}", var_id); }
         }
     }
 
@@ -601,12 +601,12 @@ impl RegionMaps {
                         scope_a
                     } else {
                         // neither fn encloses the other
-                        unreachable!()
+                        bug!()
                     }
                 }
                 _ => {
                     // root ids are always Misc right now
-                    unreachable!()
+                    bug!()
                 }
             };
         }
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 6342599bf73..d3757629d30 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -747,9 +747,9 @@ impl<'a> LifetimeContext<'a> {
                        lifetime_ref: &hir::Lifetime,
                        def: DefRegion) {
         if lifetime_ref.id == ast::DUMMY_NODE_ID {
-            self.sess.span_bug(lifetime_ref.span,
-                               "lifetime reference not renumbered, \
-                               probably a bug in syntax::fold");
+            span_bug!(lifetime_ref.span,
+                      "lifetime reference not renumbered, \
+                       probably a bug in syntax::fold");
         }
 
         debug!("lifetime_ref={:?} id={:?} resolved to {:?}",
@@ -822,7 +822,7 @@ fn early_bound_lifetime_names(generics: &hir::Generics) -> Vec<ast::Name> {
                         collector.visit_lifetime(bound);
                     }
                 }
-                &hir::WherePredicate::EqPredicate(_) => unimplemented!()
+                &hir::WherePredicate::EqPredicate(_) => bug!("unimplemented")
             }
         }
     }
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 3a2f995a318..e589743222b 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -516,8 +516,8 @@ pub fn check_expr(tcx: &TyCtxt, e: &hir::Expr,
             span = field.span;
             match tcx.expr_ty_adjusted(base_e).sty {
                 ty::TyStruct(def, _) => def.struct_variant().field_named(field.node).did,
-                _ => tcx.sess.span_bug(e.span,
-                                       "stability::check_expr: named field access on non-struct")
+                _ => span_bug!(e.span,
+                               "stability::check_expr: named field access on non-struct")
             }
         }
         hir::ExprTupField(ref base_e, ref field) => {
@@ -525,9 +525,9 @@ pub fn check_expr(tcx: &TyCtxt, e: &hir::Expr,
             match tcx.expr_ty_adjusted(base_e).sty {
                 ty::TyStruct(def, _) => def.struct_variant().fields[field.node].did,
                 ty::TyTuple(..) => return,
-                _ => tcx.sess.span_bug(e.span,
-                                       "stability::check_expr: unnamed field access on \
-                                        something other than a tuple or struct")
+                _ => span_bug!(e.span,
+                               "stability::check_expr: unnamed field access on \
+                                something other than a tuple or struct")
             }
         }
         hir::ExprStruct(_, ref expr_fields, _) => {
@@ -551,10 +551,10 @@ pub fn check_expr(tcx: &TyCtxt, e: &hir::Expr,
                 // a bug to have construct one.
                 ty::TyEnum(..) => return,
                 _ => {
-                    tcx.sess.span_bug(e.span,
-                                      &format!("stability::check_expr: struct construction \
-                                                of non-struct, type {:?}",
-                                               type_));
+                    span_bug!(e.span,
+                              "stability::check_expr: struct construction \
+                               of non-struct, type {:?}",
+                              type_);
                 }
             }
         }
diff --git a/src/librustc/mir/repr.rs b/src/librustc/mir/repr.rs
index bc10d0c90ef..a33ee6bd204 100644
--- a/src/librustc/mir/repr.rs
+++ b/src/librustc/mir/repr.rs
@@ -1016,7 +1016,7 @@ fn fmt_const_val<W: Write>(fmt: &mut W, const_val: &ConstVal) -> fmt::Result {
         Struct(node_id) | Tuple(node_id) | Array(node_id, _) | Repeat(node_id, _) =>
             write!(fmt, "{}", node_to_string(node_id)),
         Char(c) => write!(fmt, "{:?}", c),
-        Dummy => unreachable!(),
+        Dummy => bug!(),
     }
 }
 
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 46d99dbef8c..ecac5d2f73f 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -70,7 +70,7 @@ impl<'tcx> LvalueTy<'tcx> {
                                              variant_index: index }
                     }
                     _ => {
-                        tcx.sess.bug(&format!("cannot downcast non-enum type: `{:?}`", self))
+                        bug!("cannot downcast non-enum type: `{:?}`", self)
                     }
                 },
             ProjectionElem::Field(_, fty) => LvalueTy::Ty { ty: fty }
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index eba3332c8f7..4d4ba50bd4a 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -362,7 +362,7 @@ macro_rules! options {
                                                              value, $outputname,
                                                              key, type_desc))
                         }
-                        (None, None) => unreachable!()
+                        (None, None) => bug!()
                     }
                 }
                 found = true;
diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs
index 09c6b54d99c..e54acf3fdc3 100644
--- a/src/librustc/session/filesearch.rs
+++ b/src/librustc/session/filesearch.rs
@@ -155,14 +155,14 @@ pub fn get_or_default_sysroot() -> PathBuf {
                 // gcc chokes on verbatim paths which fs::canonicalize generates
                 // so we try to avoid those kinds of paths.
                 Ok(canon) => Some(rustcfs::fix_windows_verbatim_for_gcc(&canon)),
-                Err(e) => panic!("failed to get realpath: {}", e),
+                Err(e) => bug!("failed to get realpath: {}", e),
             }
         })
     }
 
     match canonicalize(env::current_exe().ok()) {
         Some(mut p) => { p.pop(); p.pop(); p }
-        None => panic!("can't determine value for sysroot")
+        None => bug!("can't determine value for sysroot")
     }
 }
 
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 20ca6213254..d3005ff2ded 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -12,6 +12,7 @@ use lint;
 use middle::cstore::CrateStore;
 use middle::dependency_format;
 use session::search_paths::PathKind;
+use ty::tls;
 use util::nodemap::{NodeMap, FnvHashMap};
 use mir::transform as mir_pass;
 
@@ -35,6 +36,7 @@ use std::cell::{Cell, RefCell};
 use std::collections::{HashMap, HashSet};
 use std::env;
 use std::rc::Rc;
+use std::fmt;
 
 pub mod config;
 pub mod filesearch;
@@ -216,22 +218,10 @@ impl Session {
             None => self.warn(msg),
         }
     }
-    pub fn opt_span_bug<S: Into<MultiSpan>>(&self, opt_sp: Option<S>, msg: &str) -> ! {
-        match opt_sp {
-            Some(sp) => self.span_bug(sp, msg),
-            None => self.bug(msg),
-        }
-    }
     /// Delay a span_bug() call until abort_if_errors()
     pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
         self.diagnostic().delay_span_bug(sp, msg)
     }
-    pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
-        self.diagnostic().span_bug(sp, msg)
-    }
-    pub fn bug(&self, msg: &str) -> ! {
-        self.diagnostic().bug(msg)
-    }
     pub fn note_without_error(&self, msg: &str) {
         self.diagnostic().note_without_error(msg)
     }
@@ -268,7 +258,7 @@ impl Session {
 
         match id.checked_add(count) {
             Some(next) => self.next_node_id.set(next),
-            None => self.bug("Input too large, ran out of node ids!")
+            None => bug!("Input too large, ran out of node ids!")
         }
 
         id
@@ -279,11 +269,6 @@ impl Session {
     pub fn codemap<'a>(&'a self) -> &'a codemap::CodeMap {
         self.parse_sess.codemap()
     }
-    // This exists to help with refactoring to eliminate impossible
-    // cases later on
-    pub fn impossible_case<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
-        self.span_bug(sp, &format!("impossible case reached: {}", msg));
-    }
     pub fn verbose(&self) -> bool { self.opts.debugging_opts.verbose }
     pub fn time_passes(&self) -> bool { self.opts.debugging_opts.time_passes }
     pub fn count_llvm_insns(&self) -> bool {
@@ -541,3 +526,35 @@ pub fn compile_result_from_err_count(err_count: usize) -> CompileResult {
         Err(err_count)
     }
 }
+
+#[cold]
+#[inline(never)]
+pub fn bug_fmt(file: &'static str, line: u32, args: fmt::Arguments) -> ! {
+    // this wrapper mostly exists so I don't have to write a fully
+    // qualified path of None::<Span> inside the bug!() macro defintion
+    opt_span_bug_fmt(file, line, None::<Span>, args);
+}
+
+#[cold]
+#[inline(never)]
+pub fn span_bug_fmt<S: Into<MultiSpan>>(file: &'static str,
+                                        line: u32,
+                                        span: S,
+                                        args: fmt::Arguments) -> ! {
+    opt_span_bug_fmt(file, line, Some(span), args);
+}
+
+fn opt_span_bug_fmt<S: Into<MultiSpan>>(file: &'static str,
+                                          line: u32,
+                                          span: Option<S>,
+                                          args: fmt::Arguments) -> ! {
+    tls::with_opt(move |tcx| {
+        let msg = format!("{}:{}: {}", file, line, args);
+        match (tcx, span) {
+            (Some(tcx), Some(span)) => tcx.sess.diagnostic().span_bug(span, &msg),
+            (Some(tcx), None) => tcx.sess.diagnostic().bug(&msg),
+            (None, _) => panic!(msg)
+        }
+    });
+    unreachable!();
+}
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index b5b5da62080..a0ac5148526 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -291,9 +291,7 @@ fn ty_is_local_constructor<'tcx>(tcx: &TyCtxt<'tcx>,
         }
 
         ty::TyClosure(..) => {
-            tcx.sess.bug(
-                &format!("ty_is_local invoked on unexpected type: {:?}",
-                        ty))
+            bug!("ty_is_local invoked on unexpected type: {:?}", ty)
         }
     }
 }
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index c26aaeaf143..f15b9ee44ce 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -201,7 +201,7 @@ pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
 
     err.emit();
     infcx.tcx.sess.abort_if_errors();
-    unreachable!();
+    bug!();
 }
 
 /// Reports that a cycle was detected which led to overflow and halts
@@ -268,9 +268,9 @@ pub fn try_report_overflow_error_type_of_infinite_size<'a, 'tcx>(
                      }
                  }
                  _ => {
-                     infcx.tcx.sess.span_bug(obligation.cause.span,
-                                             &format!("Sized cycle involving non-trait-ref: {:?}",
-                                                      obligation.predicate));
+                     span_bug!(obligation.cause.span,
+                               "Sized cycle involving non-trait-ref: {:?}",
+                               obligation.predicate);
                  }
              })
              .collect();
@@ -323,7 +323,7 @@ pub fn try_report_overflow_error_type_of_infinite_size<'a, 'tcx>(
     }
     err.emit();
     infcx.tcx.sess.abort_if_errors();
-    unreachable!();
+    bug!();
 }
 
 pub fn recursive_type_with_infinite_size_error<'tcx>(tcx: &TyCtxt<'tcx>,
@@ -472,9 +472,10 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                         // ambiguity; otherwise, they always
                         // degenerate into other obligations
                         // (which may fail).
-                        infcx.tcx.sess.span_bug(
+                        span_bug!(
                             obligation.cause.span,
-                            &format!("WF predicate not satisfied for {:?}", ty));
+                            "WF predicate not satisfied for {:?}",
+                            ty);
                     }
                 }
             }
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 3adaf5fa6bb..f7b75c2259e 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -719,8 +719,8 @@ fn project_type<'cx,'tcx>(
                     // The essential problem here is that the projection fails,
                     // leaving two unnormalized types, which appear not to unify
                     // -- so the overlap check succeeds, when it should fail.
-                    selcx.tcx().sess.bug("Tried to project an inherited associated type during \
-                                          coherence checking, which is currently not supported.");
+                    bug!("Tried to project an inherited associated type during \
+                          coherence checking, which is currently not supported.");
                 }
             }
         }
@@ -858,10 +858,10 @@ fn assemble_candidates_from_object_type<'cx,'tcx>(
     let data = match object_ty.sty {
         ty::TyTrait(ref data) => data,
         _ => {
-            selcx.tcx().sess.span_bug(
+            span_bug!(
                 obligation.cause.span,
-                &format!("assemble_candidates_from_object_type called with non-object: {:?}",
-                         object_ty));
+                "assemble_candidates_from_object_type called with non-object: {:?}",
+                object_ty);
         }
     };
     let projection_bounds = data.projection_bounds_with_self_ty(selcx.tcx(), object_ty);
@@ -951,10 +951,10 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
         super::VtableDefaultImpl(..) |
         super::VtableBuiltin(..) => {
             // These traits have no associated types.
-            selcx.tcx().sess.span_bug(
+            span_bug!(
                 obligation.cause.span,
-                &format!("Cannot project an associated type from `{:?}`",
-                         vtable));
+                "Cannot project an associated type from `{:?}`",
+                vtable);
         }
     }
 
@@ -1084,12 +1084,12 @@ fn confirm_param_env_candidate<'cx,'tcx>(
                               projection.projection_ty.trait_ref.clone()) {
         Ok(()) => { }
         Err(e) => {
-            selcx.tcx().sess.span_bug(
+            span_bug!(
                 obligation.cause.span,
-                &format!("Failed to unify `{:?}` and `{:?}` in projection: {}",
-                         obligation,
-                         projection,
-                         e));
+                "Failed to unify `{:?}` and `{:?}` in projection: {}",
+                obligation,
+                projection,
+                e);
         }
     }
 
@@ -1124,8 +1124,9 @@ fn confirm_impl_candidate<'cx,'tcx>(
             (ty.subst(tcx, substs), nested)
         }
         None => {
-            tcx.sess.span_bug(obligation.cause.span,
-                              &format!("No associated type for {:?}", trait_ref));
+            span_bug!(obligation.cause.span,
+                      "No associated type for {:?}",
+                      trait_ref);
         }
     }
 }
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index e2a48688d4b..7635ff1eb4c 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -1088,7 +1088,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let trait_def_id = match obligation.predicate.0.trait_ref.self_ty().sty {
             ty::TyProjection(ref data) => data.trait_ref.def_id,
             ty::TyInfer(ty::TyVar(_)) => {
-                self.tcx().sess.span_bug(obligation.cause.span,
+                span_bug!(obligation.cause.span,
                     "Self=_ should have been handled by assemble_candidates");
             }
             _ => { return; }
@@ -1125,11 +1125,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let projection_trait_ref = match skol_trait_predicate.trait_ref.self_ty().sty {
             ty::TyProjection(ref data) => &data.trait_ref,
             _ => {
-                self.tcx().sess.span_bug(
+                span_bug!(
                     obligation.cause.span,
-                    &format!("match_projection_obligation_against_bounds_from_trait() called \
-                              but self-ty not a projection: {:?}",
-                             skol_trait_predicate.trait_ref.self_ty()));
+                    "match_projection_obligation_against_bounds_from_trait() called \
+                     but self-ty not a projection: {:?}",
+                    skol_trait_predicate.trait_ref.self_ty());
             }
         };
         debug!("match_projection_obligation_against_bounds_from_trait: \
@@ -1601,7 +1601,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ObjectCandidate |
             ParamCandidate(_) | ProjectionCandidate => match victim.candidate {
                 DefaultImplCandidate(..) => {
-                    self.tcx().sess.bug(
+                    bug!(
                         "default implementations shouldn't be recorded \
                          when there are other valid candidates");
                 }
@@ -1703,7 +1703,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::BoundSized => ok_if(Vec::new()),
 
                     ty::BoundSync | ty::BoundSend => {
-                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                        bug!("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1713,7 +1713,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::BoundCopy | ty::BoundSized => ok_if(Vec::new()),
 
                     ty::BoundSync | ty::BoundSend => {
-                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                        bug!("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1741,7 +1741,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                         }
                     }
                     ty::BoundSync | ty::BoundSend => {
-                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                        bug!("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1762,7 +1762,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::BoundSized => ok_if(Vec::new()),
 
                     ty::BoundSync | ty::BoundSend => {
-                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                        bug!("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1773,7 +1773,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     ty::BoundCopy => ok_if(vec![element_ty]),
                     ty::BoundSized => ok_if(Vec::new()),
                     ty::BoundSync | ty::BoundSend => {
-                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                        bug!("Send/Sync shouldn't occur in builtin_bounds()");
                     }
                 }
             }
@@ -1781,7 +1781,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::TyStr | ty::TySlice(_) => {
                 match bound {
                     ty::BoundSync | ty::BoundSend => {
-                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
+                        bug!("Send/Sync shouldn't occur in builtin_bounds()");
                     }
 
                     ty::BoundCopy | ty::BoundSized => Err(Unimplemented),
@@ -1847,10 +1847,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::TyInfer(ty::FreshTy(_))
             | ty::TyInfer(ty::FreshIntTy(_))
             | ty::TyInfer(ty::FreshFloatTy(_)) => {
-                self.tcx().sess.bug(
-                    &format!(
-                        "asked to assemble builtin bounds of unexpected type: {:?}",
-                        self_ty));
+                bug!("asked to assemble builtin bounds of unexpected type: {:?}",
+                     self_ty);
             }
         };
 
@@ -1872,7 +1870,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 ty::BoundSized => ok_if(types),
 
                 // Shouldn't be coming through here.
-                ty::BoundSend | ty::BoundSync => unreachable!(),
+                ty::BoundSend | ty::BoundSync => bug!(),
             }
         }
     }
@@ -1911,10 +1909,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             ty::TyInfer(ty::FreshTy(_)) |
             ty::TyInfer(ty::FreshIntTy(_)) |
             ty::TyInfer(ty::FreshFloatTy(_)) => {
-                self.tcx().sess.bug(
-                    &format!(
-                        "asked to assemble constituent types of unexpected type: {:?}",
-                        t));
+                bug!("asked to assemble constituent types of unexpected type: {:?}",
+                     t);
             }
 
             ty::TyBox(referent_ty) => {  // Box<T>
@@ -2135,10 +2131,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         match self.match_where_clause_trait_ref(obligation, param.clone()) {
             Ok(obligations) => obligations,
             Err(()) => {
-                self.tcx().sess.bug(
-                    &format!("Where clause `{:?}` was applicable to `{:?}` but now is not",
-                             param,
-                             obligation));
+                bug!("Where clause `{:?}` was applicable to `{:?}` but now is not",
+                     param,
+                     obligation);
             }
         }
     }
@@ -2155,10 +2150,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         match self.builtin_bound(bound, obligation)? {
             If(nested) => Ok(self.vtable_builtin_data(obligation, bound, nested)),
             AmbiguousBuiltin | ParameterBuiltin => {
-                self.tcx().sess.span_bug(
+                span_bug!(
                     obligation.cause.span,
-                    &format!("builtin bound for {:?} was ambig",
-                            obligation));
+                    "builtin bound for {:?} was ambig",
+                    obligation);
             }
         }
     }
@@ -2175,7 +2170,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let trait_def = match self.tcx().lang_items.from_builtin_kind(bound) {
             Ok(def_id) => def_id,
             Err(_) => {
-                self.tcx().sess.bug("builtin trait definition not found");
+                bug!("builtin trait definition not found");
             }
         };
 
@@ -2238,10 +2233,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 self.vtable_default_impl(obligation, trait_def_id, all_types)
             }
             _ => {
-                self.tcx().sess.bug(
-                    &format!(
-                        "asked to confirm default object implementation for non-object type: {:?}",
-                        self_ty));
+                bug!("asked to confirm default object implementation for non-object type: {:?}",
+                     self_ty);
             }
         }
     }
@@ -2360,8 +2353,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 data.principal_trait_ref_with_self_ty(self.tcx(), self_ty)
             }
             _ => {
-                self.tcx().sess.span_bug(obligation.cause.span,
-                                         "object candidate with non-object");
+                span_bug!(obligation.cause.span,
+                          "object candidate with non-object");
             }
         };
 
@@ -2667,7 +2660,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     vec![inner_target]));
             }
 
-            _ => unreachable!()
+            _ => bug!()
         };
 
         Ok(VtableBuiltinData { nested: nested })
@@ -2692,10 +2685,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         match self.match_impl(impl_def_id, obligation, snapshot) {
             Ok((substs, skol_map)) => (substs, skol_map),
             Err(()) => {
-                self.tcx().sess.bug(
-                    &format!("Impl {:?} was matchable against {:?} but now is not",
-                            impl_def_id,
-                            obligation));
+                bug!("Impl {:?} was matchable against {:?} but now is not",
+                     impl_def_id,
+                     obligation);
             }
         }
     }
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index e0ce54115eb..88f4129d886 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -93,10 +93,8 @@ pub fn translate_substs<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             }
 
             fulfill_implication(infcx, source_trait_ref, target_impl).unwrap_or_else(|_| {
-                infcx.tcx
-                     .sess
-                     .bug("When translating substitutions for specialization, the expected \
-                           specializaiton failed to hold")
+                bug!("When translating substitutions for specialization, the expected \
+                      specializaiton failed to hold")
             })
         }
         specialization_graph::Node::Trait(..) => source_trait_ref.substs.clone(),
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index eaafeb1a969..d3146697ee6 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -145,8 +145,8 @@ impl Graph {
     /// Insert cached metadata mapping from a child impl back to its parent.
     pub fn record_impl_from_cstore(&mut self, parent: DefId, child: DefId) {
         if self.parent.insert(child, parent).is_some() {
-            panic!("When recording an impl from the crate store, information about its parent \
-                    was already present.");
+            bug!("When recording an impl from the crate store, information about its parent \
+                  was already present.");
         }
 
         self.children.entry(parent).or_insert(vec![]).push(child);
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index f339b6e50ce..befca878bc0 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -481,8 +481,8 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &TyCtxt<'tcx>,
         }
     }
 
-    tcx.sess.bug(&format!("get_vtable_index_of_object_method: {:?} was not found",
-                          method_def_id));
+    bug!("get_vtable_index_of_object_method: {:?} was not found",
+         method_def_id);
 }
 
 pub enum TupleArgumentsFlag { Yes, No }
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index dc2117b1ad1..90ccdeea928 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -159,9 +159,8 @@ impl<'tcx> ty::TyS<'tcx> {
                                 cx.mk_ty(ty::TyFnPtr(b))
                             }
                             _ => {
-                                cx.sess.bug(
-                                    &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
-                                              {:?}", self));
+                                bug!("AdjustReifyFnPointer adjustment on non-fn-item: {:?}",
+                                     self);
                             }
                         }
                     }
@@ -170,10 +169,8 @@ impl<'tcx> ty::TyS<'tcx> {
                         match self.sty {
                             ty::TyFnPtr(b) => cx.safe_to_unsafe_fn_ty(b),
                             ref b => {
-                                cx.sess.bug(
-                                    &format!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: \
-                                             {:?}",
-                                            b));
+                                bug!("AdjustUnsafeFnPointer adjustment on non-fn-ptr: {:?}",
+                                     b);
                             }
                         }
                     }
@@ -185,10 +182,8 @@ impl<'tcx> ty::TyS<'tcx> {
                                 mutbl: hir::MutImmutable
                             }),
                             ref b => {
-                                cx.sess.bug(
-                                    &format!("AdjustMutToConstPointer on non-raw-ptr: \
-                                             {:?}",
-                                            b));
+                                bug!("AdjustMutToConstPointer on non-raw-ptr: {:?}",
+                                     b);
                             }
                         }
                     }
@@ -239,12 +234,11 @@ impl<'tcx> ty::TyS<'tcx> {
         match adjusted_ty.builtin_deref(true, NoPreference) {
             Some(mt) => mt.ty,
             None => {
-                cx.sess.span_bug(
+                span_bug!(
                     expr_span,
-                    &format!("the {}th autoderef failed: {}",
-                             autoderef,
-                             adjusted_ty)
-                        );
+                    "the {}th autoderef failed: {}",
+                    autoderef,
+                    adjusted_ty);
             }
         }
     }
diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs
index cb84b198222..ba237184a9f 100644
--- a/src/librustc/ty/contents.rs
+++ b/src/librustc/ty/contents.rs
@@ -247,7 +247,7 @@ impl<'tcx> ty::TyS<'tcx> {
 
                 ty::TyInfer(_) |
                 ty::TyError => {
-                    cx.sess.bug("asked to compute contents of error type");
+                    bug!("asked to compute contents of error type");
                 }
             };
 
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 49e9eda5651..842a58571e0 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -462,8 +462,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let did = def.trait_ref.def_id;
         let interned = self.arenas.trait_defs.alloc(def);
         if let Some(prev) = self.trait_defs.borrow_mut().insert(did, interned) {
-            self.sess.bug(&format!("Tried to overwrite interned TraitDef: {:?}",
-                                   prev))
+            bug!("Tried to overwrite interned TraitDef: {:?}", prev)
         }
         interned
     }
@@ -482,8 +481,7 @@ impl<'tcx> TyCtxt<'tcx> {
         let interned = self.arenas.adt_defs.alloc(def);
         // this will need a transmute when reverse-variance is removed
         if let Some(prev) = self.adt_defs.borrow_mut().insert(did, interned) {
-            self.sess.bug(&format!("Tried to overwrite interned AdtDef: {:?}",
-                                   prev))
+            bug!("Tried to overwrite interned AdtDef: {:?}", prev)
         }
         interned
     }
@@ -497,16 +495,14 @@ impl<'tcx> TyCtxt<'tcx> {
         if let Some(prev) = self.stability_interner
                                 .borrow_mut()
                                 .insert(interned, interned) {
-            self.sess.bug(&format!("Tried to overwrite interned Stability: {:?}",
-                                   prev))
+            bug!("Tried to overwrite interned Stability: {:?}", prev)
         }
         interned
     }
 
     pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) {
         if self.free_region_maps.borrow_mut().insert(id, map).is_some() {
-            self.sess.bug(&format!("Tried to overwrite interned FreeRegionMap for NodeId {:?}",
-                                   id))
+            bug!("Tried to overwrite interned FreeRegionMap for NodeId {:?}", id)
         }
     }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 5c754fc12d7..edfad09ae1f 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1241,9 +1241,8 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                     cx.region_maps.call_site_extent(id, body.id))
                             }
                             _ => {
-                                cx.sess
-                                  .bug("ParameterEnvironment::for_item(): \
-                                        got non-method item from impl method?!")
+                                bug!("ParameterEnvironment::for_item(): \
+                                      got non-method item from impl method?!")
                             }
                         }
                     }
@@ -1295,10 +1294,9 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                     extent)
                             }
                             _ => {
-                                cx.sess
-                                  .bug("ParameterEnvironment::for_item(): \
-                                        got non-method item from provided \
-                                        method?!")
+                                bug!("ParameterEnvironment::for_item(): \
+                                      got non-method item from provided \
+                                      method?!")
                             }
                         }
                     }
@@ -1341,10 +1339,10 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                                                            cx.region_maps.item_extent(id))
                     }
                     _ => {
-                        cx.sess.span_bug(item.span,
-                                         "ParameterEnvironment::for_item():
-                                          can't create a parameter \
-                                          environment for this kind of item")
+                        span_bug!(item.span,
+                                  "ParameterEnvironment::for_item():
+                                   can't create a parameter \
+                                   environment for this kind of item")
                     }
                 }
             }
@@ -1353,9 +1351,9 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                 ParameterEnvironment::for_item(cx, cx.map.get_parent(id))
             }
             _ => {
-                cx.sess.bug(&format!("ParameterEnvironment::for_item(): \
-                                     `{}` is not an item",
-                                    cx.map.node_to_string(id)))
+                bug!("ParameterEnvironment::from_item(): \
+                      `{}` is not an item",
+                     cx.map.node_to_string(id))
             }
         }
     }
@@ -1649,7 +1647,7 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> {
         match def {
             Def::Variant(_, vid) => self.variant_with_id(vid),
             Def::Struct(..) | Def::TyAlias(..) => self.struct_variant(),
-            _ => panic!("unexpected def {:?} in variant_of_def", def)
+            _ => bug!("unexpected def {:?} in variant_of_def", def)
         }
     }
 
@@ -1859,7 +1857,7 @@ fn lookup_locally_or_in_crate_store<M, F>(descr: &str,
 {
     map.memoize(def_id, || {
         if def_id.is_local() {
-            panic!("No def'n found for {:?} in tcx.{}", def_id, descr);
+            bug!("No def'n found for {:?} in tcx.{}", def_id, descr);
         }
         load_external()
     })
@@ -1902,9 +1900,8 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> {
         match self.node_id_to_type_opt(id) {
            Some(ty) => ty,
-           None => self.sess.bug(
-               &format!("node_id_to_type: no type for node `{}`",
-                        self.map.node_to_string(id)))
+           None => bug!("node_id_to_type: no type for node `{}`",
+                        self.map.node_to_string(id))
         }
     }
 
@@ -1980,12 +1977,10 @@ impl<'tcx> TyCtxt<'tcx> {
                 e.span
             }
             Some(f) => {
-                self.sess.bug(&format!("Node id {} is not an expr: {:?}",
-                                       id, f));
+                bug!("Node id {} is not an expr: {:?}", id, f);
             }
             None => {
-                self.sess.bug(&format!("Node id {} is not present \
-                                        in the node map", id));
+                bug!("Node id {} is not present in the node map", id);
             }
         }
     }
@@ -1996,11 +1991,11 @@ impl<'tcx> TyCtxt<'tcx> {
                 match pat.node {
                     PatKind::Ident(_, ref path1, _) => path1.node.name.as_str(),
                     _ => {
-                        self.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, pat));
+                        bug!("Variable id {} maps to {:?}, not local", id, pat);
                     },
                 }
             },
-            r => self.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, r)),
+            r => bug!("Variable id {} maps to {:?}, not local", id, r),
         }
     }
 
@@ -2008,8 +2003,7 @@ impl<'tcx> TyCtxt<'tcx> {
         match self.def_map.borrow().get(&expr.id) {
             Some(def) => def.full_def(),
             None => {
-                self.sess.span_bug(expr.span, &format!(
-                    "no def-map entry for expr {}", expr.id));
+                span_bug!(expr.span, "no def-map entry for expr {}", expr.id);
             }
         }
     }
@@ -2032,8 +2026,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     }
                     Some(&def::PathResolution { base_def: Def::Err, .. })=> true,
                     Some(..) => false,
-                    None => self.sess.span_bug(expr.span, &format!(
-                        "no def for path {}", expr.id))
+                    None => span_bug!(expr.span, "no def for path {}", expr.id)
                 }
             }
 
@@ -2085,9 +2078,9 @@ impl<'tcx> TyCtxt<'tcx> {
                         match self.impl_or_trait_item(self.map.local_def_id(ti.id)) {
                             MethodTraitItem(m) => Some(m),
                             _ => {
-                                self.sess.bug("provided_trait_methods(): \
-                                               non-method item found from \
-                                               looking up provided method?!")
+                                bug!("provided_trait_methods(): \
+                                      non-method item found from \
+                                      looking up provided method?!")
                             }
                         }
                     } else {
@@ -2095,7 +2088,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     }
                 }).collect()
             } else {
-                self.sess.bug(&format!("provided_trait_methods: `{:?}` is not a trait", id))
+                bug!("provided_trait_methods: `{:?}` is not a trait", id)
             }
         } else {
             self.sess.cstore.provided_trait_methods(self, id)
@@ -2111,9 +2104,9 @@ impl<'tcx> TyCtxt<'tcx> {
                             match self.impl_or_trait_item(self.map.local_def_id(ti.id)) {
                                 ConstTraitItem(ac) => Some(ac),
                                 _ => {
-                                    self.sess.bug("associated_consts(): \
-                                                   non-const item found from \
-                                                   looking up a constant?!")
+                                    bug!("associated_consts(): \
+                                          non-const item found from \
+                                          looking up a constant?!")
                                 }
                             }
                         } else {
@@ -2127,9 +2120,9 @@ impl<'tcx> TyCtxt<'tcx> {
                             match self.impl_or_trait_item(self.map.local_def_id(ii.id)) {
                                 ConstTraitItem(ac) => Some(ac),
                                 _ => {
-                                    self.sess.bug("associated_consts(): \
-                                                   non-const item found from \
-                                                   looking up a constant?!")
+                                    bug!("associated_consts(): \
+                                          non-const item found from \
+                                          looking up a constant?!")
                                 }
                             }
                         } else {
@@ -2138,8 +2131,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     }).collect()
                 }
                 _ => {
-                    self.sess.bug(&format!("associated_consts: `{:?}` is not a trait \
-                                            or impl", id))
+                    bug!("associated_consts: `{:?}` is not a trait or impl", id)
                 }
             }
         } else {
@@ -2174,9 +2166,9 @@ impl<'tcx> TyCtxt<'tcx> {
             match kind {
                 Some(kind) => kind,
                 None => {
-                    self.sess.bug(&format!("custom_coerce_unsized_kind: \
-                                            {} impl `{}` is missing its kind",
-                                           src, self.item_path_str(did)));
+                    bug!("custom_coerce_unsized_kind: \
+                          {} impl `{}` is missing its kind",
+                          src, self.item_path_str(did));
                 }
             }
         })
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 635af0a98e2..b39cb5ef939 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -453,7 +453,7 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
         (_, &ty::TyInfer(_)) =>
         {
             // The caller should handle these cases!
-            tcx.sess.bug("var types encountered in super_relate_tys")
+            bug!("var types encountered in super_relate_tys")
         }
 
         (&ty::TyError, _) | (_, &ty::TyError) =>
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index dae12824da2..fee0aaff445 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -259,7 +259,7 @@ impl<'tcx> Decodable for &'tcx ClosureSubsts<'tcx> {
                                                               Box::new(closure_substs));
             match ty.sty {
                 TyClosure(_, ref closure_substs) => Ok(&**closure_substs),
-                _ => unreachable!()
+                _ => bug!()
             }
         })
     }
@@ -467,7 +467,7 @@ impl<'tcx> FnOutput<'tcx> {
     pub fn unwrap(self) -> Ty<'tcx> {
         match self {
             ty::FnConverging(t) => t,
-            ty::FnDiverging => unreachable!()
+            ty::FnDiverging => bug!()
         }
     }
 
@@ -978,8 +978,7 @@ impl<'tcx> TyS<'tcx> {
         match self.sty {
             TyArray(ty, _) | TySlice(ty) => ty,
             TyStr => cx.mk_mach_uint(ast::UintTy::U8),
-            _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
-                                      self)),
+            _ => bug!("sequence_element_type called on non-sequence value: {}", self),
         }
     }
 
@@ -988,14 +987,14 @@ impl<'tcx> TyS<'tcx> {
             TyStruct(def, substs) => {
                 def.struct_variant().fields[0].ty(cx, substs)
             }
-            _ => panic!("simd_type called on invalid type")
+            _ => bug!("simd_type called on invalid type")
         }
     }
 
     pub fn simd_size(&self, _cx: &TyCtxt) -> usize {
         match self.sty {
             TyStruct(def, _) => def.struct_variant().fields.len(),
-            _ => panic!("simd_size called on invalid type")
+            _ => bug!("simd_size called on invalid type")
         }
     }
 
@@ -1148,7 +1147,7 @@ impl<'tcx> TyS<'tcx> {
     pub fn fn_sig(&self) -> &'tcx PolyFnSig<'tcx> {
         match self.sty {
             TyFnDef(_, _, ref f) | TyFnPtr(ref f) => &f.sig,
-            _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self)
+            _ => bug!("Ty::fn_sig() called on non-fn type: {:?}", self)
         }
     }
 
@@ -1156,7 +1155,7 @@ impl<'tcx> TyS<'tcx> {
     pub fn fn_abi(&self) -> abi::Abi {
         match self.sty {
             TyFnDef(_, _, ref f) | TyFnPtr(ref f) => f.abi,
-            _ => panic!("Ty::fn_abi() called on non-fn type"),
+            _ => bug!("Ty::fn_abi() called on non-fn type"),
         }
     }
 
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index 8d257282121..5b05c632a97 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -193,7 +193,7 @@ impl ParamSpace {
             0 => TypeSpace,
             1 => SelfSpace,
             2 => FnSpace,
-            _ => panic!("Invalid ParamSpace: {}", u)
+            _ => bug!("Invalid ParamSpace: {}", u)
         }
     }
 }
@@ -604,15 +604,15 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
                     }
                     None => {
                         let span = self.span.unwrap_or(DUMMY_SP);
-                        self.tcx().sess.span_bug(
+                        span_bug!(
                             span,
-                            &format!("Region parameter out of range \
-                                      when substituting in region {} (root type={:?}) \
-                                      (space={:?}, index={})",
-                                     data.name,
-                                     self.root_ty,
-                                     data.space,
-                                     data.index));
+                            "Region parameter out of range \
+                             when substituting in region {} (root type={:?}) \
+                             (space={:?}, index={})",
+                            data.name,
+                            self.root_ty,
+                            data.space,
+                            data.index);
                     }
                 }
             }
@@ -659,16 +659,16 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> {
             Some(t) => *t,
             None => {
                 let span = self.span.unwrap_or(DUMMY_SP);
-                self.tcx().sess.span_bug(
+                span_bug!(
                     span,
-                    &format!("Type parameter `{:?}` ({:?}/{:?}/{}) out of range \
-                                 when substituting (root type={:?}) substs={:?}",
-                            p,
-                            source_ty,
-                            p.space,
-                            p.idx,
-                            self.root_ty,
-                            self.substs));
+                    "Type parameter `{:?}` ({:?}/{:?}/{}) out of range \
+                         when substituting (root type={:?}) substs={:?}",
+                    p,
+                    source_ty,
+                    p.space,
+                    p.idx,
+                    self.root_ty,
+                    self.substs);
             }
         };
 
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index a3aa3f31cd1..6e8363f629b 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -62,7 +62,7 @@ impl IntTypeExt for attr::IntType {
             SignedInt(ast::IntTy::Is) => match tcx.sess.target.int_type {
                 ast::IntTy::I32 => ConstInt::Isize(ConstIsize::Is32(0)),
                 ast::IntTy::I64 => ConstInt::Isize(ConstIsize::Is64(0)),
-                _ => unreachable!(),
+                _ => bug!(),
             },
             UnsignedInt(ast::UintTy::U8)  => ConstInt::U8(0),
             UnsignedInt(ast::UintTy::U16) => ConstInt::U16(0),
@@ -71,7 +71,7 @@ impl IntTypeExt for attr::IntType {
             UnsignedInt(ast::UintTy::Us) => match tcx.sess.target.uint_type {
                 ast::UintTy::U32 => ConstInt::Usize(ConstUsize::Us32(0)),
                 ast::UintTy::U64 => ConstInt::Usize(ConstUsize::Us64(0)),
-                _ => unreachable!(),
+                _ => bug!(),
             },
         }
     }
@@ -88,7 +88,7 @@ impl IntTypeExt for attr::IntType {
             (UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => {},
             (UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => {},
             (UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => {},
-            _ => panic!("disr type mismatch: {:?} vs {:?}", self, val),
+            _ => bug!("disr type mismatch: {:?} vs {:?}", self, val),
         }
     }
 
@@ -351,7 +351,7 @@ impl<'tcx> TyCtxt<'tcx> {
                     ty::ReScope(..) |
                     ty::ReVar(..) |
                     ty::ReSkolemized(..) => {
-                        tcx.sess.bug("unexpected region found when hashing a type")
+                        bug!("unexpected region found when hashing a type")
                     }
                 }
             };
@@ -453,7 +453,7 @@ impl<'tcx> TyCtxt<'tcx> {
                         hash!(p.idx);
                         hash!(p.name.as_str());
                     }
-                    TyInfer(_) => unreachable!(),
+                    TyInfer(_) => bug!(),
                     TyError => byte!(21),
                     TyClosure(d, _) => {
                         byte!(22);
@@ -632,7 +632,7 @@ impl<'tcx> ty::TyS<'tcx> {
                 TyClosure(..) => {
                     // this check is run on type definitions, so we don't expect
                     // to see closure types
-                    cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
+                    bug!("requires check invoked on inapplicable type: {:?}", ty)
                 }
                 _ => Representability::Representable,
             }
diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs
index 2d38b665cf9..d1b30bb2746 100644
--- a/src/librustc_borrowck/borrowck/fragments.rs
+++ b/src/librustc_borrowck/borrowck/fragments.rs
@@ -27,7 +27,7 @@ use rustc::middle::mem_categorization as mc;
 use std::mem;
 use std::rc::Rc;
 use syntax::ast;
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
 use syntax::attr::AttrMetaMethods;
 
 #[derive(PartialEq, Eq, PartialOrd, Ord)]
@@ -428,8 +428,8 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
             let tuple_idx = match *origin_field_name {
                 mc::PositionalField(tuple_idx) => tuple_idx,
                 mc::NamedField(_) =>
-                    panic!("tuple type {:?} should not have named fields.",
-                           parent_ty),
+                    bug!("tuple type {:?} should not have named fields.",
+                         parent_ty),
             };
             let tuple_len = v.len();
             for i in 0..tuple_len {
@@ -493,10 +493,11 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
         }
 
         ref sty_and_variant_info => {
-            let msg = format!("type {:?} ({:?}) is not fragmentable",
-                              parent_ty, sty_and_variant_info);
             let opt_span = origin_id.and_then(|id|tcx.map.opt_span(id));
-            tcx.sess.opt_span_bug(opt_span, &msg[..])
+            span_bug!(opt_span.unwrap_or(DUMMY_SP),
+                      "type {:?} ({:?}) is not fragmentable",
+                      parent_ty,
+                      sty_and_variant_info);
         }
     }
 }
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 107109c9115..489c8be4e38 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -78,8 +78,8 @@ pub fn gather_match_variant<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                 LpDowncast(ref base_lp, _) =>
                     move_data.add_variant_match(
                         tcx, lp.clone(), move_pat.id, base_lp.clone(), mode),
-                _ => panic!("should only call gather_match_variant \
-                             for cat_downcast cmt"),
+                _ => bug!("should only call gather_match_variant \
+                           for cat_downcast cmt"),
             }
         }
         None => {
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index 247f8121de7..c759722c24b 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -378,10 +378,10 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
                     ty::ReEarlyBound(..) |
                     ty::ReVar(..) |
                     ty::ReSkolemized(..) => {
-                        self.tcx().sess.span_bug(
+                        span_bug!(
                             cmt.span,
-                            &format!("invalid borrow lifetime: {:?}",
-                                    loan_region));
+                            "invalid borrow lifetime: {:?}",
+                            loan_region);
                     }
                 };
                 debug!("loan_scope = {:?}", loan_scope);
diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
index f49554289b3..f5e3bc4f6fb 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
@@ -134,8 +134,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                   a non-copy fixed-size array",
                                  b.ty)
             } else {
-                bccx.span_bug(move_from.span, "this path should not cause illegal move");
-                unreachable!();
+                span_bug!(move_from.span, "this path should not cause illegal move");
             }
         }
 
@@ -150,14 +149,12 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                                      b.ty)
                 },
                 _ => {
-                    bccx.span_bug(move_from.span, "this path should not cause illegal move");
-                    unreachable!();
+                    span_bug!(move_from.span, "this path should not cause illegal move");
                 }
             }
         }
         _ => {
-            bccx.span_bug(move_from.span, "this path should not cause illegal move");
-            unreachable!();
+            span_bug!(move_from.span, "this path should not cause illegal move");
         }
     }
 }
diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
index dbe58799341..2b1b743afe9 100644
--- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
@@ -569,7 +569,7 @@ fn gather_moves<'tcx>(mir: &Mir<'tcx>, tcx: &TyCtxt<'tcx>) -> MoveData<'tcx> {
                         Rvalue::InlineAsm { .. } => {}
 
                         Rvalue::Slice {..} => {
-                            bb_ctxt.tcx.sess.bug("cannot move out of slice");
+                            bug!("cannot move out of slice");
                         }
                     }
                 }
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index d985359a3dd..1dfa4da46aa 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -420,10 +420,10 @@ pub fn closure_to_block(closure_id: ast::NodeId,
                 block.id
             }
             _ => {
-                panic!("encountered non-closure id: {}", closure_id)
+                bug!("encountered non-closure id: {}", closure_id)
             }
         },
-        _ => panic!("encountered non-expr id: {}", closure_id)
+        _ => bug!("encountered non-expr id: {}", closure_id)
     }
 }
 
@@ -704,10 +704,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                         (self.tcx.expr_ty_adjusted(&expr), expr.span)
                     }
                     r => {
-                        self.tcx.sess.bug(&format!("MoveExpr({}) maps to \
-                                                   {:?}, not Expr",
-                                                  the_move.id,
-                                                  r))
+                        bug!("MoveExpr({}) maps to {:?}, not Expr",
+                             the_move.id,
+                             r)
                     }
                 };
                 let (suggestion, _) =
@@ -766,10 +765,9 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                         (self.tcx.expr_ty_adjusted(&expr), expr.span)
                     }
                     r => {
-                        self.tcx.sess.bug(&format!("Captured({}) maps to \
-                                                   {:?}, not Expr",
-                                                  the_move.id,
-                                                  r))
+                        bug!("Captured({}) maps to {:?}, not Expr",
+                             the_move.id,
+                             r)
                     }
                 };
                 let (suggestion, help) =
@@ -852,10 +850,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         self.tcx.sess.span_err_with_code(s, msg, code);
     }
 
-    pub fn span_bug(&self, s: Span, m: &str) {
-        self.tcx.sess.span_bug(s, m);
-    }
-
     pub fn bckerr_to_string(&self, err: &BckError<'tcx>) -> String {
         match err.code {
             err_mutbl => {
@@ -895,7 +889,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                         format!("cannot borrow {} as mutable", descr)
                     }
                     BorrowViolation(euv::ClosureInvocation) => {
-                        self.tcx.sess.span_bug(err.span,
+                        span_bug!(err.span,
                             "err_mutbl with a closure invocation");
                     }
                 }
@@ -1035,7 +1029,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                         // We need to determine which is the case here.
                         let kind = match err.cmt.upvar().unwrap().cat {
                             Categorization::Upvar(mc::Upvar { kind, .. }) => kind,
-                            _ => unreachable!()
+                            _ => bug!()
                         };
                         if kind == ty::ClosureKind::Fn {
                             db.span_help(
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index 00274fe1a04..b31f74c6476 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -515,7 +515,7 @@ impl<'tcx> MoveData<'tcx> {
                                          assignment_index);
                 }
                 LpExtend(..) => {
-                    tcx.sess.bug("var assignment for non var path");
+                    bug!("var assignment for non var path");
                 }
             }
         }
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index 1aa27f8b32b..6f21fcd9230 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -32,6 +32,7 @@
 // for "clarity", rename the graphviz crate to dot; graphviz within `borrowck`
 // refers to the borrowck-specific graphviz adapter traits.
 extern crate graphviz as dot;
+#[macro_use]
 extern crate rustc;
 extern crate rustc_front;
 extern crate rustc_mir;
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index f00df1f671f..a46d72840b7 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -339,7 +339,7 @@ fn check_arms(cx: &MatchCheckCtxt,
                             // `Some(<head>)` and `None`. It's impossible to have an unreachable
                             // pattern
                             // (see libsyntax/ext/expand.rs for the full expansion of a for loop)
-                            cx.tcx.sess.span_bug(pat.span, "unreachable for-loop pattern")
+                            span_bug!(pat.span, "unreachable for-loop pattern")
                         },
 
                         hir::MatchSource::Normal => {
@@ -347,12 +347,12 @@ fn check_arms(cx: &MatchCheckCtxt,
                         },
 
                         hir::MatchSource::TryDesugar => {
-                            cx.tcx.sess.span_bug(pat.span, "unreachable try pattern")
+                            span_bug!(pat.span, "unreachable try pattern")
                         },
                     }
                 }
                 Useful => (),
-                UsefulWithWitness(_) => unreachable!()
+                UsefulWithWitness(_) => bug!()
             }
             if guard.is_none() {
                 let Matrix(mut rows) = seen;
@@ -384,9 +384,9 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir:
                     let witness = match witnesses[0].node {
                         PatKind::TupleStruct(_, Some(ref pats)) => match &pats[..] {
                             [ref pat] => &**pat,
-                            _ => unreachable!(),
+                            _ => bug!(),
                         },
-                        _ => unreachable!(),
+                        _ => bug!(),
                     };
                     span_err!(cx.tcx.sess, sp, E0297,
                         "refutable pattern in `for` loop binding: \
@@ -399,7 +399,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir:
                     }).collect();
                     const LIMIT: usize = 3;
                     let joined_patterns = match pattern_strings.len() {
-                        0 => unreachable!(),
+                        0 => bug!(),
                         1 => format!("`{}`", pattern_strings[0]),
                         2...LIMIT => {
                             let (tail, head) = pattern_strings.split_last().unwrap();
@@ -420,14 +420,14 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: hir:
         NotUseful => {
             // This is good, wildcard pattern isn't reachable
         },
-        _ => unreachable!()
+        _ => bug!()
     }
 }
 
 fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
     let node = match value {
         &ConstVal::Bool(b) => ast::LitKind::Bool(b),
-        _ => unreachable!()
+        _ => bug!()
     };
     P(hir::Expr {
         id: 0,
@@ -579,14 +579,14 @@ fn construct_witness<'a,'tcx>(cx: &MatchCheckCtxt<'a,'tcx>, ctor: &Constructor,
                         assert_eq!(pats_len, n);
                         PatKind::Vec(pats.collect(), None, hir::HirVec::new())
                     },
-                    _ => unreachable!()
+                    _ => bug!()
                 },
                 ty::TySlice(_) => match ctor {
                     &Slice(n) => {
                         assert_eq!(pats_len, n);
                         PatKind::Vec(pats.collect(), None, hir::HirVec::new())
                     },
-                    _ => unreachable!()
+                    _ => bug!()
                 },
                 ty::TyStr => PatKind::Wild,
 
@@ -791,17 +791,16 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
         PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::Ident(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def() {
                 Def::Const(..) | Def::AssociatedConst(..) =>
-                    cx.tcx.sess.span_bug(pat.span, "const pattern should've \
-                                                    been rewritten"),
+                    span_bug!(pat.span, "const pattern should've \
+                                         been rewritten"),
                 Def::Struct(..) | Def::TyAlias(..) => vec![Single],
                 Def::Variant(_, id) => vec![Variant(id)],
                 Def::Local(..) => vec![],
-                def => cx.tcx.sess.span_bug(pat.span, &format!("pat_constructors: unexpected \
-                                                                definition {:?}", def)),
+                def => span_bug!(pat.span, "pat_constructors: unexpected \
+                                            definition {:?}", def),
             },
         PatKind::QPath(..) =>
-            cx.tcx.sess.span_bug(pat.span, "const pattern should've \
-                                            been rewritten"),
+            span_bug!(pat.span, "const pattern should've been rewritten"),
         PatKind::Lit(ref expr) =>
             vec!(ConstantValue(eval_const_expr(cx.tcx, &expr))),
         PatKind::Range(ref lo, ref hi) =>
@@ -837,7 +836,7 @@ pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> us
             ty::TySlice(_) => match *ctor {
                 Slice(length) => length,
                 ConstantValue(_) => 0,
-                _ => unreachable!()
+                _ => bug!()
             },
             ty::TyStr => 0,
             _ => 1
@@ -856,7 +855,7 @@ fn range_covered_by_constructor(ctor: &Constructor,
         ConstantValue(ref value)        => (value, value),
         ConstantRange(ref from, ref to) => (from, to),
         Single                          => return Some(true),
-        _                               => unreachable!()
+        _                               => bug!()
     };
     let cmp_from = compare_const_vals(c_from, from);
     let cmp_to = compare_const_vals(c_to, to);
@@ -889,13 +888,13 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
                 Def::Const(..) | Def::AssociatedConst(..) =>
-                    cx.tcx.sess.span_bug(pat_span, "const pattern should've \
-                                                    been rewritten"),
+                    span_bug!(pat_span, "const pattern should've \
+                                         been rewritten"),
                 Def::Variant(_, id) if *constructor != Variant(id) => None,
                 Def::Variant(..) | Def::Struct(..) => Some(Vec::new()),
                 Def::Local(..) => Some(vec![DUMMY_WILD_PAT; arity]),
-                _ => cx.tcx.sess.span_bug(pat_span, &format!("specialize: unexpected \
-                                                              definition {:?}", def)),
+                _ => span_bug!(pat_span, "specialize: unexpected \
+                                          definition {:?}", def),
             }
         }
 
@@ -903,8 +902,8 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
                 Def::Const(..) | Def::AssociatedConst(..) =>
-                    cx.tcx.sess.span_bug(pat_span, "const pattern should've \
-                                                    been rewritten"),
+                    span_bug!(pat_span, "const pattern should've \
+                                         been rewritten"),
                 Def::Variant(_, id) if *constructor != Variant(id) => None,
                 Def::Variant(..) | Def::Struct(..) => {
                     Some(match args {
@@ -917,8 +916,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         }
 
         PatKind::QPath(_, _) => {
-            cx.tcx.sess.span_bug(pat_span, "const pattern should've \
-                                            been rewritten")
+            span_bug!(pat_span, "const pattern should've been rewritten")
         }
 
         PatKind::Struct(_, ref pattern_fields, _) => {
@@ -1062,7 +1060,7 @@ fn is_refutable<A, F>(cx: &MatchCheckCtxt, pat: &Pat, refutable: F) -> Option<A>
     match is_useful(cx, &pats, &[DUMMY_WILD_PAT], ConstructWitness) {
         UsefulWithWitness(pats) => Some(refutable(&pats[0])),
         NotUseful => None,
-        Useful => unreachable!()
+        Useful => bug!()
     }
 }
 
@@ -1119,12 +1117,11 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
                     PatKind::Ident(hir::BindByRef(_), _, _) => {
                     }
                     _ => {
-                        cx.tcx.sess.span_bug(
+                        span_bug!(
                             p.span,
-                            &format!("binding pattern {} is not an \
-                                     identifier: {:?}",
-                                    p.id,
-                                    p.node));
+                            "binding pattern {} is not an identifier: {:?}",
+                            p.id,
+                            p.node);
                     }
                 }
             }
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index a36d0b3fcff..4790e481937 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -286,7 +286,7 @@ pub fn const_expr_to_pat(tcx: &ty::TyCtxt, expr: &Expr, pat_id: ast::NodeId, spa
                     node: PatKind::Lit(P(expr.clone())),
                     span: span,
                 })),
-                _ => unreachable!()
+                _ => bug!()
             };
             let pats = try!(args.iter()
                                 .map(|expr| const_expr_to_pat(tcx, &**expr,
@@ -330,7 +330,7 @@ pub fn const_expr_to_pat(tcx: &ty::TyCtxt, expr: &Expr, pat_id: ast::NodeId, spa
                     let (expr, _ty) = lookup_const_by_id(tcx, def_id, substs).unwrap();
                     return const_expr_to_pat(tcx, expr, pat_id, span);
                 },
-                _ => unreachable!(),
+                _ => bug!(),
             }
         }
 
@@ -588,7 +588,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
                         IntTy::I64 => if n == I64_OVERFLOW {
                             return Ok(Integral(Isize(Is64(::std::i64::MIN))));
                         },
-                        _ => unreachable!(),
+                        _ => bug!(),
                     }
                 },
                 _ => {},
@@ -697,7 +697,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
                     Some(IntType::UnsignedInt(ty)) => ty_hint.checked_or(tcx.mk_mach_uint(ty)),
                     Some(IntType::SignedInt(ty)) => ty_hint.checked_or(tcx.mk_mach_int(ty)),
                     // we had a type hint, so we can't have an unknown type
-                    None => unreachable!(),
+                    None => bug!(),
                 };
                 eval_const_expr_partial(tcx, &base, hint, fn_args)?
             },
@@ -798,7 +798,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
       hir::ExprBlock(ref block) => {
         match block.expr {
             Some(ref expr) => eval_const_expr_partial(tcx, &expr, ty_hint, fn_args)?,
-            None => unreachable!(),
+            None => bug!(),
         }
       }
       hir::ExprType(ref e, _) => eval_const_expr_partial(tcx, &e, ty_hint, fn_args)?,
@@ -813,7 +813,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
         let idx_hint = ty_hint.checked_or(tcx.types.usize);
         let idx = match eval_const_expr_partial(tcx, idx, idx_hint, fn_args)? {
             Integral(Usize(i)) => i.as_u64(tcx.sess.target.uint_type),
-            Integral(_) => unreachable!(),
+            Integral(_) => bug!(),
             _ => signal!(idx, IndexNotInt),
         };
         assert_eq!(idx as usize as u64, idx);
@@ -823,7 +823,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
                 assert_eq!(n as usize as u64, n);
                 eval_const_expr_partial(tcx, &v[idx as usize], ty_hint, fn_args)?
             } else {
-                unreachable!()
+                bug!()
             },
 
             Repeat(_, n) if idx >= n => signal!(e, IndexOutOfBounds),
@@ -840,7 +840,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
             },
 
             Str(ref s) if idx as usize >= s.len() => signal!(e, IndexOutOfBounds),
-            Str(_) => unimplemented!(), // FIXME: return a const char
+            Str(_) => bug!("unimplemented"), // FIXME: return a const char
             _ => signal!(e, IndexedNonVec),
         }
       }
@@ -867,7 +867,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
                     signal!(e, TupleIndexOutOfBounds);
                 }
             } else {
-                unreachable!()
+                bug!()
             }
         } else {
             signal!(base, ExpectedConstTuple);
@@ -888,7 +888,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
                     signal!(e, MissingStructField);
                 }
             } else {
-                unreachable!()
+                bug!()
             }
         } else {
             signal!(base, ExpectedConstStruct);
@@ -1025,7 +1025,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
             }
         }
         _ => {
-            tcx.sess.span_bug(
+            span_bug!(
                 ti.span,
                 "resolve_trait_associated_const: unexpected vtable type")
         }
@@ -1127,7 +1127,7 @@ fn lit_to_const<'tcx>(lit: &ast::LitKind,
                     let int_ty = tcx.enum_repr_type(hints.iter().next());
                     infer(Infer(n), tcx, &int_ty.to_ty(tcx).sty, span).map(Integral)
                 },
-                Some(ty_hint) => panic!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
+                Some(ty_hint) => bug!("bad ty_hint: {:?}, {:?}", ty_hint, lit),
             }
         },
         LitKind::Int(n, Unsigned(ity)) => {
@@ -1140,7 +1140,7 @@ fn lit_to_const<'tcx>(lit: &ast::LitKind,
                 Ok(Float(x))
             } else {
                 // FIXME(#31407) this is only necessary because float parsing is buggy
-                tcx.sess.span_bug(span, "could not evaluate float literal (see issue #31407)");
+                span_bug!(span, "could not evaluate float literal (see issue #31407)");
             }
         }
         LitKind::Bool(b) => Ok(Bool(b)),
diff --git a/src/librustc_const_eval/lib.rs b/src/librustc_const_eval/lib.rs
index 558ae71756b..b74fc121e39 100644
--- a/src/librustc_const_eval/lib.rs
+++ b/src/librustc_const_eval/lib.rs
@@ -32,7 +32,7 @@
 
 #[macro_use] extern crate syntax;
 #[macro_use] extern crate log;
-extern crate rustc;
+#[macro_use] extern crate rustc;
 extern crate rustc_front;
 extern crate rustc_back;
 extern crate rustc_const_math;
diff --git a/src/librustc_lint/bad_style.rs b/src/librustc_lint/bad_style.rs
index 66d435a7581..ca189d0b519 100644
--- a/src/librustc_lint/bad_style.rs
+++ b/src/librustc_lint/bad_style.rs
@@ -30,7 +30,7 @@ pub enum MethodLateContext {
 pub fn method_context(cx: &LateContext, id: ast::NodeId, span: Span) -> MethodLateContext {
     let def_id = cx.tcx.map.local_def_id(id);
     match cx.tcx.impl_or_trait_items.borrow().get(&def_id) {
-        None => cx.sess().span_bug(span, "missing method descriptor?!"),
+        None => span_bug!(span, "missing method descriptor?!"),
         Some(item) => match item.container() {
             ty::TraitContainer(..) => MethodLateContext::TraitDefaultImpl,
             ty::ImplContainer(cid) => {
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 80733bccf8e..6eeadc77698 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -181,7 +181,7 @@ impl LateLintPass for TypeLimits {
                                     return;
                                 }
                             }
-                            _ => panic!()
+                            _ => bug!()
                         };
                     },
                     ty::TyUint(t) => {
@@ -195,7 +195,7 @@ impl LateLintPass for TypeLimits {
                             // _v is u8, within range by definition
                             ast::LitKind::Byte(_v) => return,
                             ast::LitKind::Int(v, _) => v,
-                            _ => panic!()
+                            _ => bug!()
                         };
                         if lit_val < min || lit_val > max {
                             cx.span_lint(OVERFLOWING_LITERALS, e.span,
@@ -212,7 +212,7 @@ impl LateLintPass for TypeLimits {
                                     Err(_) => return
                                 }
                             }
-                            _ => panic!()
+                            _ => bug!()
                         };
                         if lit_val < min || lit_val > max {
                             cx.span_lint(OVERFLOWING_LITERALS, e.span,
@@ -233,7 +233,7 @@ impl LateLintPass for TypeLimits {
                 hir::BiGt => v >= min && v <  max,
                 hir::BiGe => v >  min && v <= max,
                 hir::BiEq | hir::BiNe => v >= min && v <= max,
-                _ => panic!()
+                _ => bug!()
             }
         }
 
@@ -319,7 +319,7 @@ impl LateLintPass for TypeLimits {
                             ast::LitKind::Int(v, ast::LitIntType::Unsuffixed) => v as i64,
                             _ => return true
                         },
-                        _ => panic!()
+                        _ => bug!()
                     };
                     is_valid(norm_binop, lit_val, min, max)
                 }
@@ -330,7 +330,7 @@ impl LateLintPass for TypeLimits {
                             ast::LitKind::Int(v, _) => v,
                             _ => return true
                         },
-                        _ => panic!()
+                        _ => bug!()
                     };
                     is_valid(norm_binop, lit_val, min, max)
                 }
@@ -589,7 +589,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             ty::TyParam(..) | ty::TyInfer(..) | ty::TyError |
             ty::TyClosure(..) | ty::TyProjection(..) |
             ty::TyFnDef(..) => {
-                panic!("Unexpected type in foreign function")
+                bug!("Unexpected type in foreign function")
             }
         }
     }
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 60865888a54..505619d31d7 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -991,7 +991,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
                         region: this.read_enum_variant_arg(1,
                                     |this| Ok(this.read_region(dcx))).unwrap()
                     }),
-                    _ => panic!("bad enum variant for ty::UpvarCapture")
+                    _ => bug!("bad enum variant for ty::UpvarCapture")
                 })
             })
         }).unwrap()
@@ -1013,7 +1013,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
 
                         adjustment::AdjustDerefRef(auto_deref_ref)
                     }
-                    _ => panic!("bad enum variant for adjustment::AutoAdjustment")
+                    _ => bug!("bad enum variant for adjustment::AutoAdjustment")
                 })
             })
         }).unwrap()
@@ -1072,7 +1072,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
 
                         adjustment::AutoUnsafe(m)
                     }
-                    _ => panic!("bad enum variant for adjustment::AutoRef")
+                    _ => bug!("bad enum variant for adjustment::AutoRef")
                 })
             })
         }).unwrap()
@@ -1140,9 +1140,7 @@ fn decode_side_tables(dcx: &DecodeContext,
         let decoded_tag: Option<c::astencode_tag> = c::astencode_tag::from_u32(tag);
         match decoded_tag {
             None => {
-                dcx.tcx.sess.bug(
-                    &format!("unknown tag found in side tables: {:x}",
-                            tag));
+                bug!("unknown tag found in side tables: {:x}", tag);
             }
             Some(value) => {
                 let val_dsr = &mut entry_dsr;
@@ -1206,9 +1204,7 @@ fn decode_side_tables(dcx: &DecodeContext,
                         dcx.tcx.const_qualif_map.borrow_mut().insert(id, qualif);
                     }
                     _ => {
-                        dcx.tcx.sess.bug(
-                            &format!("unknown tag found in side tables: {:x}",
-                                    tag));
+                        bug!("unknown tag found in side tables: {:x}", tag);
                     }
                 }
             }
@@ -1404,6 +1400,6 @@ fn test_simplification() {
         assert!(pprust::item_to_string(&item_out) ==
                 pprust::item_to_string(&item_exp));
       }
-      _ => panic!()
+      _ => bug!()
     }
 }
diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs
index d07179749d9..edabf43a150 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -36,7 +36,6 @@ use syntax::codemap::{self, Span, mk_sp, Pos};
 use syntax::parse;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
-use syntax::errors::FatalError;
 use syntax::parse::token::InternedString;
 use rustc_front::intravisit::Visitor;
 use rustc_front::hir;
@@ -527,7 +526,7 @@ impl<'a> CrateReader<'a> {
                 load_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate);
                 load_ctxt.load_library_crate()
             }
-            None => { load_ctxt.report_load_errs(); unreachable!() },
+            None => { load_ctxt.report_load_errs(); },
         };
 
         let dylib = library.dylib.clone();
@@ -573,7 +572,8 @@ impl<'a> CrateReader<'a> {
                     Ok(body) => body,
                     Err(mut err) => {
                         err.emit();
-                        panic!(FatalError);
+                        self.sess.abort_if_errors();
+                        unreachable!();
                     }
                 };
                 let local_span = mk_sp(lo, p.last_span.hi);
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index b9ebd3c3afa..e85fdb05ca8 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -70,7 +70,7 @@ impl crate_metadata {
 
     fn lookup_item(&self, item_id: DefIndex) -> rbml::Doc {
         match self.get_item(item_id) {
-            None => panic!("lookup_item: id not found: {:?}", item_id),
+            None => bug!("lookup_item: id not found: {:?}", item_id),
             Some(d) => d
         }
     }
@@ -136,7 +136,7 @@ fn item_family(item: rbml::Doc) -> Family {
       'u' => Struct(VariantKind::Unit),
       'g' => PublicField,
       'N' => InheritedField,
-       c => panic!("unexpected family char: {}", c)
+       c => bug!("unexpected family char: {}", c)
     }
 }
 
@@ -147,7 +147,7 @@ fn item_visibility(item: rbml::Doc) -> hir::Visibility {
             match reader::doc_as_u8(visibility_doc) as char {
                 'y' => hir::Public,
                 'i' => hir::Inherited,
-                _ => panic!("unknown visibility character")
+                _ => bug!("unknown visibility character")
             }
         }
     }
@@ -160,7 +160,7 @@ fn fn_constness(item: rbml::Doc) -> hir::Constness {
             match reader::doc_as_u8(constness_doc) as char {
                 'c' => hir::Constness::Const,
                 'n' => hir::Constness::NotConst,
-                _ => panic!("unknown constness character")
+                _ => bug!("unknown constness character")
             }
         }
     }
@@ -173,7 +173,7 @@ fn item_defaultness(item: rbml::Doc) -> hir::Defaultness {
             match reader::doc_as_u8(defaultness_doc) as char {
                 'd' => hir::Defaultness::Default,
                 'f' => hir::Defaultness::Final,
-                _ => panic!("unknown defaultness character")
+                _ => bug!("unknown defaultness character")
             }
         }
     }
@@ -387,16 +387,15 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
                          item_id: DefIndex,
                          tcx: &TyCtxt<'tcx>) -> ty::AdtDefMaster<'tcx>
 {
-    fn expect_variant_kind<'tcx>(family: Family, tcx: &TyCtxt<'tcx>) -> ty::VariantKind {
+    fn expect_variant_kind(family: Family) -> ty::VariantKind {
         match family_to_variant_kind(family) {
             Some(kind) => kind,
-            _ => tcx.sess.bug(&format!("unexpected family: {:?}", family)),
+            _ => bug!("unexpected family: {:?}", family),
         }
     }
     fn get_enum_variants<'tcx>(intr: &IdentInterner,
                                cdata: Cmd,
-                               doc: rbml::Doc,
-                               tcx: &TyCtxt<'tcx>) -> Vec<ty::VariantDefData<'tcx, 'tcx>> {
+                               doc: rbml::Doc) -> Vec<ty::VariantDefData<'tcx, 'tcx>> {
         let mut disr_val = 0;
         reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| {
             let did = translated_def_id(cdata, p);
@@ -411,22 +410,21 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
             ty::VariantDefData {
                 did: did,
                 name: item_name(intr, item),
-                fields: get_variant_fields(intr, cdata, item, tcx),
+                fields: get_variant_fields(intr, cdata, item),
                 disr_val: ConstInt::Infer(disr),
-                kind: expect_variant_kind(item_family(item), tcx),
+                kind: expect_variant_kind(item_family(item)),
             }
         }).collect()
     }
     fn get_variant_fields<'tcx>(intr: &IdentInterner,
                                 cdata: Cmd,
-                                doc: rbml::Doc,
-                                tcx: &TyCtxt<'tcx>) -> Vec<ty::FieldDefData<'tcx, 'tcx>> {
+                                doc: rbml::Doc) -> Vec<ty::FieldDefData<'tcx, 'tcx>> {
         let mut index = 0;
         reader::tagged_docs(doc, tag_item_field).map(|f| {
             let ff = item_family(f);
             match ff {
                 PublicField | InheritedField => {},
-                _ => tcx.sess.bug(&format!("expected field, found {:?}", ff))
+                _ => bug!("expected field, found {:?}", ff)
             };
             ty::FieldDefData::new(item_def_id(f, cdata),
                                   item_name(intr, f),
@@ -442,14 +440,13 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
     fn get_struct_variant<'tcx>(intr: &IdentInterner,
                                 cdata: Cmd,
                                 doc: rbml::Doc,
-                                did: DefId,
-                                tcx: &TyCtxt<'tcx>) -> ty::VariantDefData<'tcx, 'tcx> {
+                                did: DefId) -> ty::VariantDefData<'tcx, 'tcx> {
         ty::VariantDefData {
             did: did,
             name: item_name(intr, doc),
-            fields: get_variant_fields(intr, cdata, doc, tcx),
+            fields: get_variant_fields(intr, cdata, doc),
             disr_val: ConstInt::Infer(0),
-            kind: expect_variant_kind(item_family(doc), tcx),
+            kind: expect_variant_kind(item_family(doc)),
         }
     }
 
@@ -458,18 +455,17 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
     let (kind, variants) = match item_family(doc) {
         Enum => {
             (ty::AdtKind::Enum,
-             get_enum_variants(intr, cdata, doc, tcx))
+             get_enum_variants(intr, cdata, doc))
         }
         Struct(..) => {
             let ctor_did =
                 reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).
                 map_or(did, |ctor_doc| translated_def_id(cdata, ctor_doc));
             (ty::AdtKind::Struct,
-             vec![get_struct_variant(intr, cdata, doc, ctor_did, tcx)])
+             vec![get_struct_variant(intr, cdata, doc, ctor_did)])
         }
-        _ => tcx.sess.bug(
-            &format!("get_adt_def called on a non-ADT {:?} - {:?}",
-                     item_family(doc), did))
+        _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}",
+                  item_family(doc), did)
     };
 
     let adt = tcx.intern_adt_def(did, kind, variants);
@@ -495,7 +491,7 @@ pub fn get_adt_def<'tcx>(intr: &IdentInterner,
                     assert!(!inputs.has_escaping_regions());
                     inputs
                 },
-                _ => tcx.sess.bug("tuple-variant ctor is not an ADT")
+                _ => bug!("tuple-variant ctor is not an ADT")
             };
             for (field, &ty) in variant.fields.iter().zip(field_tys.iter()) {
                 field.fulfill_ty(ty);
@@ -915,7 +911,7 @@ fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
         match ch as char {
             'i' => hir::MutImmutable,
             'm' => hir::MutMutable,
-            _ => panic!("unknown mutability character: `{}`", ch as char),
+            _ => bug!("unknown mutability character: `{}`", ch as char),
         }
     }
 
@@ -933,7 +929,7 @@ fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
                 ty::ReEmpty,
                 get_mutability(string.as_bytes()[1]))
         }
-        _ => panic!("unknown self type code: `{}`", explicit_self_kind as char)
+        _ => bug!("unknown self type code: `{}`", explicit_self_kind as char)
     }
 }
 
@@ -946,7 +942,7 @@ pub fn get_impl_items(cdata: Cmd, impl_id: DefIndex)
             Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
             Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
             Some('t') => ty::TypeTraitItemId(def_id),
-            _ => panic!("unknown impl item sort"),
+            _ => bug!("unknown impl item sort"),
         }
     }).collect()
 }
@@ -1012,9 +1008,9 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
             let ity = tcx.lookup_item_type(def_id).ty;
             let fty = match ity.sty {
                 ty::TyFnDef(_, _, fty) => fty.clone(),
-                _ => tcx.sess.bug(&format!(
+                _ => bug!(
                     "the type {:?} of the method {:?} is not a function?",
-                    ity, name))
+                    ity, name)
             };
             let explicit_self = get_explicit_self(item_doc);
 
@@ -1052,7 +1048,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: DefIndex)
             Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
             Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
             Some('t') => ty::TypeTraitItemId(def_id),
-            _ => panic!("unknown trait item sort"),
+            _ => bug!("unknown trait item sort"),
         }
     }).collect()
 }
@@ -1172,7 +1168,7 @@ fn struct_field_family_to_visibility(family: Family) -> hir::Visibility {
     match family {
       PublicField => hir::Public,
       InheritedField => hir::Inherited,
-      _ => panic!()
+      _ => bug!()
     }
 }
 
@@ -1354,7 +1350,7 @@ pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId {
                 index: did.index,
             }
         }
-        None => panic!("didn't find a crate in the cnum_map")
+        None => bug!("didn't find a crate in the cnum_map")
     }
 }
 
@@ -1544,7 +1540,7 @@ pub fn get_dylib_dependency_formats(cdata: Cmd)
         let cnum: ast::CrateNum = cnum.parse().unwrap();
         let cnum = match cdata.cnum_map.borrow().get(&cnum) {
             Some(&n) => n,
-            None => panic!("didn't find a crate in the cnum_map")
+            None => bug!("didn't find a crate in the cnum_map")
         };
         result.push((cnum, if link == "d" {
             LinkagePreference::RequireDynamic
@@ -1772,7 +1768,7 @@ pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey {
             hir_map::DefKey::decode(&mut decoder).unwrap()
         }
         None => {
-            panic!("failed to find block with tag {:?} for item with family {:?}",
+            bug!("failed to find block with tag {:?} for item with family {:?}",
                    tag_def_key,
                    item_family(item_doc))
         }
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 0a23cdee23d..30eabb7e8f3 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -217,7 +217,7 @@ fn encode_symbol(ecx: &EncodeContext,
             rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
         }
         None => {
-            ecx.diag.bug(&format!("encode_symbol: id not found {}", id));
+            bug!("encode_symbol: id not found {}", id);
         }
     }
 }
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 674106dd82a..c927f53eccd 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -33,6 +33,7 @@ extern crate flate;
 extern crate rbml;
 extern crate serialize;
 
+#[macro_use]
 extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_front;
diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs
index 07a736d9959..87e86e221f1 100644
--- a/src/librustc_metadata/loader.rs
+++ b/src/librustc_metadata/loader.rs
@@ -300,16 +300,10 @@ impl<'a> Context<'a> {
     }
 
     pub fn load_library_crate(&mut self) -> Library {
-        match self.find_library_crate() {
-            Some(t) => t,
-            None => {
-                self.report_load_errs();
-                unreachable!()
-            }
-        }
+        self.find_library_crate().unwrap_or_else(|| self.report_load_errs())
     }
 
-    pub fn report_load_errs(&mut self) {
+    pub fn report_load_errs(&mut self) -> ! {
         let add = match self.root {
             &None => String::new(),
             &Some(ref r) => format!(" which `{}` depends on",
@@ -374,6 +368,7 @@ impl<'a> Context<'a> {
 
         err.emit();
         self.sess.abort_if_errors();
+        unreachable!();
     }
 
     fn find_library_crate(&mut self) -> Option<Library> {
diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs
index ed59fce77a0..28985c75a91 100644
--- a/src/librustc_metadata/tydecode.rs
+++ b/src/librustc_metadata/tydecode.rs
@@ -167,7 +167,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 ty::BrFresh(id)
             }
             'e' => ty::BrEnv,
-            _ => panic!("parse_bound_region: bad input")
+            _ => bug!("parse_bound_region: bad input")
         }
     }
 
@@ -214,7 +214,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             'e' => {
                 ty::ReStatic
             }
-            _ => panic!("parse_region: bad input")
+            _ => bug!("parse_region: bad input")
         }
     }
 
@@ -266,7 +266,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 };
                 region::CodeExtentData::Remainder(block_remainder)
             }
-            _ => panic!("parse_scope: bad input")
+            _ => bug!("parse_scope: bad input")
         })
     }
 
@@ -276,7 +276,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         match self.next() {
             'n' => None,
             's' => Some(f(self)),
-            _ => panic!("parse_opt: bad input")
+            _ => bug!("parse_opt: bad input")
         }
     }
 
@@ -315,7 +315,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                     'D' => return tcx.types.i64,
                     'f' => return tcx.types.f32,
                     'F' => return tcx.types.f64,
-                    _ => panic!("parse_ty: bad numeric type")
+                    _ => bug!("parse_ty: bad numeric type")
                 }
             }
             'c' => return tcx.types.char,
@@ -441,7 +441,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
             'e' => {
                 return tcx.types.err;
             }
-            c => { panic!("unexpected char in type string: {}", c);}
+            c => { bug!("unexpected char in type string: {}", c);}
         }
     }
 
@@ -523,7 +523,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
         let variadic = match self.next() {
             'V' => true,
             'N' => false,
-            r => panic!(format!("bad variadic: {}", r)),
+            r => bug!("bad variadic: {}", r),
         };
         let output = match self.peek() {
             'z' => {
@@ -553,7 +553,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 assert_eq!(self.next(), '|');
                 ty::Predicate::ObjectSafe(def_id)
             }
-            c => panic!("Encountered invalid character in metadata: {}", c)
+            c => bug!("Encountered invalid character in metadata: {}", c)
         }
     }
 
@@ -602,7 +602,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 'R' => bounds.push(self.parse_region()),
                 '.' => { break; }
                 c => {
-                    panic!("parse_region_param_def: bad bounds ('{}')", c)
+                    bug!("parse_region_param_def: bad bounds ('{}')", c)
                 }
             }
         }
@@ -624,7 +624,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 let region = self.parse_region();
                 ty::ObjectLifetimeDefault::Specific(region)
             }
-            _ => panic!("parse_object_lifetime_default: bad input")
+            _ => bug!("parse_object_lifetime_default: bad input")
         }
     }
 
@@ -640,7 +640,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                 }
                 '.' => { break; }
                 c => {
-                    panic!("parse_bounds: bad bounds ('{}')", c)
+                    bug!("parse_bounds: bad bounds ('{}')", c)
                 }
             }
         }
@@ -669,7 +669,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
                     return builtin_bounds;
                 }
                 c => {
-                    panic!("parse_bounds: bad builtin bounds ('{}')", c)
+                    bug!("parse_bounds: bad builtin bounds ('{}')", c)
                 }
             }
         }
@@ -683,7 +683,7 @@ fn parse_defid(buf: &[u8]) -> DefId {
     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }
     if colon_idx == len {
         error!("didn't find ':' when parsing def id");
-        panic!();
+        bug!();
     }
 
     let crate_part = &buf[0..colon_idx];
@@ -693,14 +693,14 @@ fn parse_defid(buf: &[u8]) -> DefId {
         s.parse::<usize>().ok()
     }) {
         Some(cn) => cn as ast::CrateNum,
-        None => panic!("internal error: parse_defid: crate number expected, found {:?}",
+        None => bug!("internal error: parse_defid: crate number expected, found {:?}",
                        crate_part)
     };
     let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
         s.parse::<usize>().ok()
     }) {
         Some(dn) => dn,
-        None => panic!("internal error: parse_defid: id expected, found {:?}",
+        None => bug!("internal error: parse_defid: id expected, found {:?}",
                        def_part)
     };
     let index = DefIndex::new(def_num);
@@ -711,6 +711,6 @@ fn parse_unsafety(c: char) -> hir::Unsafety {
     match c {
         'u' => hir::Unsafety::Unsafe,
         'n' => hir::Unsafety::Normal,
-        _ => panic!("parse_unsafety: bad unsafety {}", c)
+        _ => bug!("parse_unsafety: bad unsafety {}", c)
     }
 }
diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs
index 1d57918d173..ffaf7e2d465 100644
--- a/src/librustc_metadata/tyencode.rs
+++ b/src/librustc_metadata/tyencode.rs
@@ -146,7 +146,7 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx
             enc_bare_fn_ty(w, cx, f);
         }
         ty::TyInfer(_) => {
-            cx.diag.bug("cannot encode inference variable types");
+            bug!("cannot encode inference variable types");
         }
         ty::TyParam(ParamTy {space, idx, name}) => {
             write!(w, "p[{}|{}|{}]", idx, space.to_uint(), name);
@@ -285,7 +285,7 @@ pub fn enc_region(w: &mut Cursor<Vec<u8>>, cx: &ctxt, r: ty::Region) {
         }
         ty::ReVar(_) | ty::ReSkolemized(..) => {
             // these should not crop up after typeck
-            cx.diag.bug("cannot encode region variables");
+            bug!("cannot encode region variables");
         }
     }
 }
diff --git a/src/librustc_mir/build/expr/as_constant.rs b/src/librustc_mir/build/expr/as_constant.rs
index 6f186b8ada4..d97245a5fc2 100644
--- a/src/librustc_mir/build/expr/as_constant.rs
+++ b/src/librustc_mir/build/expr/as_constant.rs
@@ -33,9 +33,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
             ExprKind::Literal { literal } =>
                 Constant { span: span, ty: ty, literal: literal },
             _ =>
-                this.hir.span_bug(
+                span_bug!(
                     span,
-                    &format!("expression is not a valid constant {:?}", kind)),
+                    "expression is not a valid constant {:?}",
+                    kind),
         }
     }
 }
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index 30a42bcd709..a2f7d2c9d72 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -38,7 +38,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         let temp_lifetime = match expr.temp_lifetime {
             Some(t) => t,
             None => {
-                this.hir.span_bug(expr.span, "no temp_lifetime for expr");
+                span_bug!(expr.span, "no temp_lifetime for expr");
             }
         };
         this.schedule_drop(expr.span, temp_lifetime, &temp, expr_ty);
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 68563197014..cabf5c95546 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -162,10 +162,10 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         unpack!(block = self.simplify_candidate(block, &mut candidate));
 
         if !candidate.match_pairs.is_empty() {
-            self.hir.span_bug(candidate.match_pairs[0].pattern.span,
-                              &format!("match pairs {:?} remaining after simplifying \
-                                        irrefutable pattern",
-                                       candidate.match_pairs));
+            span_bug!(candidate.match_pairs[0].pattern.span,
+                      "match pairs {:?} remaining after simplifying \
+                       irrefutable pattern",
+                      candidate.match_pairs);
         }
 
         // now apply the bindings, which will also declare the variables
diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs
index dc70cf4ffb9..f70d4321a49 100644
--- a/src/librustc_mir/build/matches/test.rs
+++ b/src/librustc_mir/build/matches/test.rs
@@ -521,8 +521,9 @@ impl<'a,'tcx> Builder<'a,'tcx> {
     }
 
     fn error_simplifyable<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> ! {
-        self.hir.span_bug(match_pair.pattern.span,
-                          &format!("simplifyable pattern found: {:?}", match_pair.pattern))
+        span_bug!(match_pair.pattern.span,
+                  "simplifyable pattern found: {:?}",
+                  match_pair.pattern)
     }
 }
 
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 82f7ddebf0b..51069c38857 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -218,8 +218,8 @@ pub fn construct<'a,'tcx>(hir: Cx<'a,'tcx>,
                    .enumerate()
                    .all(|(index, block)| {
                        if block.terminator.is_none() {
-                           panic!("no terminator on block {:?} in fn {:?}",
-                               index, fn_id)
+                           bug!("no terminator on block {:?} in fn {:?}",
+                                index, fn_id)
                        }
                        true
                    }));
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index e3093eab22b..bda9cf058f6 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -306,7 +306,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
         let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent)
                                                       .unwrap_or_else(||{
-            self.hir.span_bug(span, &format!("extent {:?} does not enclose", extent))
+            span_bug!(span, "extent {:?} does not enclose", extent)
         });
 
         let tmp = self.get_unit_temp();
@@ -345,7 +345,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                            span: Span,
                            label: Option<CodeExtent>)
                            -> &mut LoopScope {
-        let Builder { ref mut loop_scopes, ref mut hir, .. } = *self;
+        let loop_scopes = &mut self.loop_scopes;
         match label {
             None => {
                 // no label? return the innermost loop scope
@@ -358,7 +358,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                            .filter(|loop_scope| loop_scope.extent == label)
                            .next()
             }
-        }.unwrap_or_else(|| hir.span_bug(span, "no enclosing loop scope found?"))
+        }.unwrap_or_else(|| span_bug!(span, "no enclosing loop scope found?"))
     }
 
     pub fn innermost_scope_id(&self) -> ScopeId {
@@ -410,8 +410,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 scope.invalidate_cache()
             }
         }
-        self.hir.span_bug(span,
-                          &format!("extent {:?} not in scope to drop {:?}", extent, lvalue));
+        span_bug!(span, "extent {:?} not in scope to drop {:?}", extent, lvalue);
     }
 
     /// Schedule dropping of a not-yet-fully-initialised box.
@@ -444,8 +443,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
                 scope.invalidate_cache();
             }
         }
-        self.hir.span_bug(span,
-                          &format!("extent {:?} not in scope to free {:?}", extent, value));
+        span_bug!(span, "extent {:?} not in scope to free {:?}", extent, value);
     }
 
     // Other
@@ -531,7 +529,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         let tup_ty = if let ty::TyRef(_, tyandmut) = ref_ty.sty {
             tyandmut.ty
         } else {
-            self.hir.span_bug(span, &format!("unexpected panic_bound_check type: {:?}", func.ty));
+            span_bug!(span, "unexpected panic_bound_check type: {:?}", func.ty);
         };
 
         let (tuple, tuple_ref) = (self.temp(tup_ty), self.temp(ref_ty));
@@ -566,7 +564,7 @@ impl<'a,'tcx> Builder<'a,'tcx> {
         let tup_ty = if let ty::TyRef(_, tyandmut) = ref_ty.sty {
             tyandmut.ty
         } else {
-            self.hir.span_bug(span, &format!("unexpected panic type: {:?}", func.ty));
+            span_bug!(span, "unexpected panic type: {:?}", func.ty);
         };
 
         let (tuple, tuple_ref) = (self.temp(tup_ty), self.temp(ref_ty));
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 451cdea35a7..7e16883e754 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -64,11 +64,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
 
                     let sig = match method.ty.sty {
                         ty::TyFnDef(_, _, fn_ty) => &fn_ty.sig,
-                        _ => cx.tcx.sess.span_bug(self.span, "type of method is not an fn")
+                        _ => span_bug!(self.span, "type of method is not an fn")
                     };
 
                     let sig = cx.tcx.no_late_bound_regions(sig).unwrap_or_else(|| {
-                        cx.tcx.sess.span_bug(self.span, "method call has late-bound regions")
+                        span_bug!(self.span, "method call has late-bound regions")
                     });
 
                     assert_eq!(sig.inputs.len(), 2);
@@ -128,7 +128,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
             hir::ExprAddrOf(mutbl, ref expr) => {
                 let region = match expr_ty.sty {
                     ty::TyRef(r, _) => r,
-                    _ => cx.tcx.sess.span_bug(expr.span, "type of & not region"),
+                    _ => span_bug!(expr.span, "type of & not region"),
                 };
                 ExprKind::Borrow {
                     region: *region,
@@ -297,16 +297,18 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                                 }
                             }
                             ref def => {
-                                cx.tcx.sess.span_bug(
+                                span_bug!(
                                     self.span,
-                                    &format!("unexpected def: {:?}", def));
+                                    "unexpected def: {:?}",
+                                    def);
                             }
                         }
                     }
                     _ => {
-                        cx.tcx.sess.span_bug(
+                        span_bug!(
                             self.span,
-                            &format!("unexpected type for struct literal: {:?}", expr_ty));
+                            "unexpected type for struct literal: {:?}",
+                            expr_ty);
                     }
                 }
             }
@@ -316,9 +318,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                 let (def_id, substs) = match closure_ty.sty {
                     ty::TyClosure(def_id, ref substs) => (def_id, substs),
                     _ => {
-                        cx.tcx.sess.span_bug(self.span,
-                                             &format!("closure expr w/o closure type: {:?}",
-                                                      closure_ty));
+                        span_bug!(self.span,
+                                  "closure expr w/o closure type: {:?}",
+                                  closure_ty);
                     }
                 };
                 let upvars = cx.tcx.with_freevars(self.id, |freevars| {
@@ -355,7 +357,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     span: c.span,
                     value: match const_eval::eval_const_expr(cx.tcx, c) {
                         ConstVal::Integral(ConstInt::Usize(u)) => u,
-                        other => panic!("constant evaluation of repeat count yielded {:?}", other),
+                        other => bug!("constant evaluation of repeat count yielded {:?}", other),
                     },
                 }
             },
@@ -383,14 +385,16 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                     ty::TyStruct(adt_def, _) =>
                         adt_def.variants[0].index_of_field_named(name.node),
                     ref ty =>
-                        cx.tcx.sess.span_bug(
+                        span_bug!(
                             self.span,
-                            &format!("field of non-struct: {:?}", ty)),
+                            "field of non-struct: {:?}",
+                            ty),
                 };
                 let index = index.unwrap_or_else(|| {
-                    cx.tcx.sess.span_bug(
+                    span_bug!(
                         self.span,
-                        &format!("no index found for field `{}`", name.node));
+                        "no index found for field `{}`",
+                        name.node)
                 });
                 ExprKind::Field { lhs: source.to_ref(), name: Field::new(index) }
             }
@@ -474,8 +478,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
                             Some(ty::FnConverging(&ty::TyS {
                                 sty: ty::TyRef(region, mt), ..
                             })) => (region, mt.mutbl),
-                            _ => cx.tcx.sess.span_bug(
-                                expr.span, "autoderef returned bad type")
+                            _ => span_bug!(expr.span, "autoderef returned bad type")
                         };
 
                         expr = Expr {
@@ -651,7 +654,7 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
                 fields: vec![],
                 base: None
             },
-            ref sty => panic!("unexpected sty: {:?}", sty)
+            ref sty => bug!("unexpected sty: {:?}", sty)
         },
         Def::Variant(enum_id, variant_id) => match cx.tcx.node_id_to_type(expr.id).sty {
             // A variant constructor. Should only be reached if not called in the same
@@ -669,7 +672,7 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
                     base: None
                 };
             },
-            ref sty => panic!("unexpected sty: {:?}", sty)
+            ref sty => bug!("unexpected sty: {:?}", sty)
         },
         Def::Const(def_id) |
         Def::AssociatedConst(def_id) => {
@@ -693,9 +696,10 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
         def @ Def::Upvar(..) => return convert_var(cx, expr, def),
 
         def =>
-            cx.tcx.sess.span_bug(
+            span_bug!(
                 expr.span,
-                &format!("def `{:?}` not yet implemented", def)),
+                "def `{:?}` not yet implemented",
+                def),
     };
     ExprKind::Literal {
         literal: Literal::Item { def_id: def_id, substs: substs }
@@ -724,12 +728,12 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
                     match expr.node {
                         hir::ExprClosure(_, _, ref body) => body.id,
                         _ => {
-                            cx.tcx.sess.span_bug(expr.span, "closure expr is not a closure expr");
+                            span_bug!(expr.span, "closure expr is not a closure expr");
                         }
                     }
                 }
                 _ => {
-                    cx.tcx.sess.span_bug(expr.span, "ast-map has garbage for closure expr");
+                    span_bug!(expr.span, "ast-map has garbage for closure expr");
                 }
             };
 
@@ -809,9 +813,10 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
             let upvar_capture = match cx.tcx.upvar_capture(upvar_id) {
                 Some(c) => c,
                 None => {
-                    cx.tcx.sess.span_bug(
+                    span_bug!(
                         expr.span,
-                        &format!("no upvar_capture for {:?}", upvar_id));
+                        "no upvar_capture for {:?}",
+                        upvar_id);
                 }
             };
             match upvar_capture {
@@ -834,7 +839,7 @@ fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
             }
         }
 
-        _ => cx.tcx.sess.span_bug(expr.span, "type of & not region"),
+        _ => span_bug!(expr.span, "type of & not region"),
     }
 }
 
@@ -857,7 +862,7 @@ fn bin_op(op: hir::BinOp_) -> BinOp {
         hir::BinOp_::BiNe => BinOp::Ne,
         hir::BinOp_::BiGe => BinOp::Ge,
         hir::BinOp_::BiGt => BinOp::Gt,
-        _ => panic!("no equivalent for ast binop {:?}", op),
+        _ => bug!("no equivalent for ast binop {:?}", op),
     }
 }
 
@@ -997,7 +1002,7 @@ fn loop_label<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> Cod
     match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
         Some(Def::Label(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
         d => {
-            cx.tcx.sess.span_bug(expr.span, &format!("loop scope resolved to {:?}", d));
+            span_bug!(expr.span, "loop scope resolved to {:?}", d);
         }
     }
 }
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index e4a8363051b..05448a7deab 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -24,7 +24,6 @@ use rustc::middle::def_id::DefId;
 use rustc::infer::InferCtxt;
 use rustc::ty::subst::{Subst, Substs};
 use rustc::ty::{self, Ty, TyCtxt};
-use syntax::codemap::Span;
 use syntax::parse::token;
 use rustc_front::hir;
 use rustc_const_math::{ConstInt, ConstUsize};
@@ -57,7 +56,7 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
     pub fn usize_literal(&mut self, value: u64) -> Literal<'tcx> {
         match ConstUsize::new(value, self.tcx.sess.target.uint_type) {
             Ok(val) => Literal::Value { value: ConstVal::Integral(ConstInt::Usize(val))},
-            Err(_) => panic!("usize literal out of range for target"),
+            Err(_) => bug!("usize literal out of range for target"),
         }
     }
 
@@ -124,7 +123,7 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
             }
         }
 
-        self.tcx.sess.bug(&format!("found no method `{}` in `{:?}`", method_name, trait_def_id));
+        bug!("found no method `{}` in `{:?}`", method_name, trait_def_id);
     }
 
     pub fn num_variants(&mut self, adt_def: ty::AdtDef<'tcx>) -> usize {
@@ -141,10 +140,6 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
         self.tcx.type_needs_drop_given_env(ty, &self.infcx.parameter_environment)
     }
 
-    pub fn span_bug(&mut self, span: Span, message: &str) -> ! {
-        self.tcx.sess.span_bug(span, message)
-    }
-
     pub fn tcx(&self) -> &'a TyCtxt<'tcx> {
         self.tcx
     }
diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs
index c6132a71eef..8ec8cd4bf81 100644
--- a/src/librustc_mir/hair/cx/pattern.rs
+++ b/src/librustc_mir/hair/cx/pattern.rs
@@ -97,21 +97,23 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                                     Ok(pat) =>
                                         return self.to_pattern(&pat),
                                     Err(_) =>
-                                        self.cx.tcx.sess.span_bug(
+                                        span_bug!(
                                             pat.span, "illegal constant"),
                                 }
                             }
                             None => {
-                                self.cx.tcx.sess.span_bug(
+                                span_bug!(
                                     pat.span,
-                                    &format!("cannot eval constant: {:?}", def_id))
+                                    "cannot eval constant: {:?}",
+                                    def_id)
                             }
                         }
                     }
                     _ =>
-                        self.cx.tcx.sess.span_bug(
+                        span_bug!(
                             pat.span,
-                            &format!("def not a constant: {:?}", def)),
+                            "def not a constant: {:?}",
+                            def),
                 }
             }
 
@@ -138,9 +140,10 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                         self.slice_or_array_pattern(pat.span, ty, prefix, slice, suffix),
 
                     ref sty =>
-                        self.cx.tcx.sess.span_bug(
+                        span_bug!(
                             pat.span,
-                            &format!("unexpanded type for vector pattern: {:?}", sty)),
+                            "unexpanded type for vector pattern: {:?}",
+                            sty),
                 }
             }
 
@@ -186,7 +189,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                     if let ty::TyRef(_, mt) = ty.sty {
                         ty = mt.ty;
                     } else {
-                        unreachable!("`ref {}` has wrong type {}", ident.node, ty);
+                        bug!("`ref {}` has wrong type {}", ident.node, ty);
                     }
                 }
 
@@ -222,7 +225,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                 let adt_def = match pat_ty.sty {
                     ty::TyStruct(adt_def, _) | ty::TyEnum(adt_def, _) => adt_def,
                     _ => {
-                        self.cx.tcx.sess.span_bug(
+                        span_bug!(
                             pat.span,
                             "struct pattern not applied to struct or enum");
                     }
@@ -236,9 +239,10 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
                           .map(|field| {
                               let index = variant_def.index_of_field_named(field.node.name);
                               let index = index.unwrap_or_else(|| {
-                                  self.cx.tcx.sess.span_bug(
+                                  span_bug!(
                                       pat.span,
-                                      &format!("no field with name {:?}", field.node.name));
+                                      "no field with name {:?}",
+                                      field.node.name);
                               });
                               FieldPattern {
                                   field: Field::new(index),
@@ -251,7 +255,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
             }
 
             PatKind::QPath(..) => {
-                self.cx.tcx.sess.span_bug(pat.span, "unexpanded macro or bad constant etc");
+                span_bug!(pat.span, "unexpanded macro or bad constant etc");
             }
         };
 
@@ -298,7 +302,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
             }
 
             _ => {
-                self.cx.tcx.sess.span_bug(span, "unexpanded macro or bad constant etc");
+                span_bug!(span, "unexpanded macro or bad constant etc");
             }
         }
     }
@@ -327,8 +331,7 @@ impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
             }
 
             _ => {
-                self.cx.tcx.sess.span_bug(pat.span,
-                                          &format!("inappropriate def for pattern: {:?}", def));
+                span_bug!(pat.span, "inappropriate def for pattern: {:?}", def);
             }
         }
     }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index e024fa94fb7..e7c0a3d9cae 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -27,6 +27,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 
 #[macro_use] extern crate log;
 extern crate graphviz as dot;
+#[macro_use]
 extern crate rustc;
 extern crate rustc_data_structures;
 extern crate rustc_front;
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index 21cc8d35320..9ec88c1b59a 100644
--- a/src/librustc_mir/mir_map.rs
+++ b/src/librustc_mir/mir_map.rs
@@ -165,8 +165,7 @@ fn build_mir<'a,'tcx:'a>(cx: Cx<'a,'tcx>,
     let fn_sig = match cx.tcx().tables.borrow().liberated_fn_sigs.get(&fn_id) {
         Some(f) => f.clone(),
         None => {
-            cx.tcx().sess.span_bug(span,
-                                   &format!("no liberated fn sig for {:?}", fn_id));
+            span_bug!(span, "no liberated fn sig for {:?}", fn_id);
         }
     };
 
diff --git a/src/librustc_passes/const_fn.rs b/src/librustc_passes/const_fn.rs
index 54dcda27b77..97a4c14863d 100644
--- a/src/librustc_passes/const_fn.rs
+++ b/src/librustc_passes/const_fn.rs
@@ -44,13 +44,13 @@ impl<'a, 'v> Visitor<'v> for CheckBlock<'a> {
             visit::walk_expr(self, e);
         }
     }
-    fn visit_item(&mut self, _i: &'v ast::Item) { panic!("should be handled in CheckConstFn") }
+    fn visit_item(&mut self, _i: &'v ast::Item) { bug!("should be handled in CheckConstFn") }
     fn visit_fn(&mut self,
                 _fk: FnKind<'v>,
                 _fd: &'v ast::FnDecl,
                 _b: &'v ast::Block,
                 _s: Span,
-                _fn_id: ast::NodeId) { panic!("should be handled in CheckConstFn") }
+                _fn_id: ast::NodeId) { bug!("should be handled in CheckConstFn") }
 }
 
 fn check_block(sess: &Session, b: &ast::Block, kind: &'static str) {
@@ -67,7 +67,7 @@ fn check_block(sess: &Session, b: &ast::Block, kind: &'static str) {
             }
             ast::StmtKind::Expr(ref expr, _) => expr.span,
             ast::StmtKind::Semi(ref semi, _) => semi.span,
-            ast::StmtKind::Mac(..) => unreachable!(),
+            ast::StmtKind::Mac(..) => bug!(),
         };
         span_err!(sess, span, E0016,
                   "blocks in {}s are limited to items and tail expressions", kind);
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index a33b8caee2e..a7f00888735 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -229,7 +229,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
             Mode::Const => "constant",
             Mode::ConstFn => "constant function",
             Mode::StaticMut | Mode::Static => "static",
-            Mode::Var => unreachable!(),
+            Mode::Var => bug!(),
         }
     }
 
@@ -400,7 +400,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 // The count is checked elsewhere (typeck).
                 let count = match node_ty.sty {
                     ty::TyArray(_, n) => n,
-                    _ => unreachable!()
+                    _ => bug!()
                 };
                 // [element; 0] is always zero-sized.
                 if count == 0 {
@@ -570,7 +570,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         hir::ExprCast(ref from, _) => {
             debug!("Checking const cast(id={})", from.id);
             match v.tcx.cast_kinds.borrow().get(&from.id) {
-                None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
+                None => span_bug!(e.span, "no kind for cast"),
                 Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
                     v.add_qualif(ConstQualif::NOT_CONST);
                     if v.mode != Mode::Var {
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index 6d217040316..44bcdcdb364 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -28,7 +28,7 @@
 #![feature(rustc_private)]
 
 extern crate core;
-extern crate rustc;
+#[macro_use] extern crate rustc;
 extern crate rustc_front;
 extern crate rustc_const_eval;
 
diff --git a/src/librustc_passes/static_recursion.rs b/src/librustc_passes/static_recursion.rs
index 329ce21edbe..2230283c977 100644
--- a/src/librustc_passes/static_recursion.rs
+++ b/src/librustc_passes/static_recursion.rs
@@ -218,9 +218,9 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
             // borrow fall out of scope, so that we can reborrow farther down.
             maybe_expr = (*get_expr).clone();
         } else {
-            self.sess.span_bug(variant.span,
-                               "`check_static_recursion` attempted to visit \
-                                variant with unknown discriminant")
+            span_bug!(variant.span,
+                      "`check_static_recursion` attempted to visit \
+                      variant with unknown discriminant")
         }
         // If `maybe_expr` is `None`, that's because no discriminant is
         // specified that affects this variant. Thus, no risk of recursion.
@@ -254,10 +254,10 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
                                     self.visit_impl_item(item),
                                 ast_map::NodeForeignItem(_) => {},
                                 _ => {
-                                    self.sess.span_bug(
+                                    span_bug!(
                                         e.span,
-                                        &format!("expected item, found {}",
-                                                 self.ast_map.node_to_string(node_id)));
+                                        "expected item, found {}",
+                                        self.ast_map.node_to_string(node_id));
                                 }
                             }
                         }
@@ -277,9 +277,9 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
                                 let variant = self.ast_map.expect_variant(variant_id);
                                 self.visit_variant(variant, generics, enum_id);
                             } else {
-                                self.sess.span_bug(e.span,
-                                                   "`check_static_recursion` found \
-                                                    non-enum in Def::Variant");
+                                span_bug!(e.span,
+                                          "`check_static_recursion` found \
+                                           non-enum in Def::Variant");
                             }
                         }
                     }
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index d4b309fb039..80df21e85f6 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -24,7 +24,7 @@
 #[macro_use] extern crate log;
 #[macro_use] extern crate syntax;
 
-extern crate rustc;
+#[macro_use] extern crate rustc;
 extern crate rustc_front;
 
 use std::cmp;
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 211bff352fe..fe44743ede3 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -507,7 +507,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
             Def::Label(..) |
             Def::SelfTy(..) |
             Def::Err => {
-                panic!("didn't expect `{:?}`", def);
+                bug!("didn't expect `{:?}`", def);
             }
         }
     }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 2f6d5e1c36e..e5576b00a76 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -32,6 +32,7 @@ extern crate arena;
 #[no_link]
 extern crate rustc_bitflags;
 extern crate rustc_front;
+#[macro_use]
 extern crate rustc;
 
 use self::PatternBindingMode::*;
@@ -2375,11 +2376,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                         // The below shouldn't happen because all
                         // qualified paths should be in PatKind::QPath.
                         TypecheckRequired =>
-                            self.session.span_bug(path.span,
-                                                  "resolve_possibly_assoc_item claimed that a path \
-                                                   in PatKind::Path or PatKind::TupleStruct \
-                                                   requires typecheck to resolve, but qualified \
-                                                   paths should be PatKind::QPath"),
+                            span_bug!(path.span,
+                                      "resolve_possibly_assoc_item claimed that a path \
+                                       in PatKind::Path or PatKind::TupleStruct \
+                                       requires typecheck to resolve, but qualified \
+                                       paths should be PatKind::QPath"),
                         ResolveAttempt(resolution) => resolution,
                     };
                     if let Some(path_res) = resolution {
@@ -2668,7 +2669,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         let mut def = local_def.def;
         match def {
             Def::Upvar(..) => {
-                self.session.span_bug(span, &format!("unexpected {:?} in bindings", def))
+                span_bug!(span, "unexpected {:?} in bindings", def)
             }
             Def::Local(_, node_id) => {
                 for rib in ribs {
@@ -3189,7 +3190,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                                         })
                     }
                     Some(_) => {
-                        self.session.span_bug(expr.span, "label wasn't mapped to a label def!")
+                        span_bug!(expr.span, "label wasn't mapped to a label def!")
                     }
                 }
             }
@@ -3346,7 +3347,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                             paths.push(segm);
                             paths
                         }
-                        _ => unreachable!(),
+                        _ => bug!(),
                     };
 
                     if !in_module_is_extern || name_binding.is_public() {
@@ -3368,10 +3369,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
         debug!("(recording def) recording {:?} for {}", resolution, node_id);
         if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) {
             let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
-            self.session.span_bug(span,
-                                  &format!("path resolved multiple times ({:?} before, {:?} now)",
-                                           prev_res,
-                                           resolution));
+            span_bug!(span,
+                      "path resolved multiple times ({:?} before, {:?} now)",
+                      prev_res,
+                      resolution);
         }
     }
 
diff --git a/src/librustc_save_analysis/data.rs b/src/librustc_save_analysis/data.rs
index 997a635f69e..649c8387eb3 100644
--- a/src/librustc_save_analysis/data.rs
+++ b/src/librustc_save_analysis/data.rs
@@ -20,17 +20,6 @@ use rustc::ty;
 use syntax::ast::{CrateNum, NodeId};
 use syntax::codemap::Span;
 
-#[macro_export]
-macro_rules! down_cast_data {
-    ($id:ident, $kind:ident, $this:ident, $sp:expr) => {
-        let $id = if let super::Data::$kind(data) = $id {
-            data
-        } else {
-            $this.sess.span_bug($sp, &format!("unexpected data kind: {:?}", $id));
-        }
-    };
-}
-
 pub struct CrateData {
     pub name: String,
     pub number: u32,
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 88b72ccf329..35ca2a9b014 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -51,11 +51,11 @@ use super::span_utils::SpanUtils;
 use super::recorder;
 
 macro_rules! down_cast_data {
-    ($id:ident, $kind:ident, $this:ident, $sp:expr) => {
+    ($id:ident, $kind:ident, $sp:expr) => {
         let $id = if let super::Data::$kind(data) = $id {
             data
         } else {
-            $this.sess.span_bug($sp, &format!("unexpected data kind: {:?}", $id));
+            span_bug!($sp, "unexpected data kind: {:?}", $id);
         }
     };
 }
@@ -271,8 +271,7 @@ where D: Dump
     // looks up anything, not just a type
     fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
         if !self.tcx.def_map.borrow().contains_key(&ref_id) {
-            self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
-                                   ref_id));
+            bug!("def_map has no key for {} in lookup_type_ref", ref_id);
         }
         let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
@@ -294,9 +293,9 @@ where D: Dump
 
         let def_map = self.tcx.def_map.borrow();
         if !def_map.contains_key(&ref_id) {
-            self.sess.span_bug(span,
-                               &format!("def_map has no key for {} in lookup_def_kind",
-                                        ref_id));
+            span_bug!(span,
+                      "def_map has no key for {} in lookup_def_kind",
+                      ref_id);
         }
         let def = def_map.get(&ref_id).unwrap().full_def();
         match def {
@@ -347,8 +346,9 @@ where D: Dump
             Def::Method(..) |
             Def::PrimTy(_) |
             Def::Err => {
-                self.sess.span_bug(span,
-                                   &format!("process_def_kind for unexpected item: {:?}", def));
+               span_bug!(span,
+                         "process_def_kind for unexpected item: {:?}",
+                         def);
             }
         }
     }
@@ -480,7 +480,7 @@ where D: Dump
                   ty_params: &ast::Generics,
                   body: &ast::Block) {
         if let Some(fn_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(fn_data, FunctionData, self, item.span);
+            down_cast_data!(fn_data, FunctionData, item.span);
             if !self.span.filter_generated(Some(fn_data.span), item.span) {
                 self.dumper.function(item.span, fn_data.clone().normalize(&self.tcx));
             }
@@ -502,7 +502,7 @@ where D: Dump
 
     fn process_static_or_const_item(&mut self, item: &ast::Item, typ: &ast::Ty, expr: &ast::Expr) {
         if let Some(var_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(var_data, VariableData, self, item.span);
+            down_cast_data!(var_data, VariableData, item.span);
             if !self.span.filter_generated(Some(var_data.span), item.span) {
                 let mut var_data = var_data;
                 var_data.scope = normalize_node_id(&self.tcx, var_data.scope) as u32;
@@ -578,7 +578,7 @@ where D: Dump
             None => return,
             Some(data) => data,
         };
-        down_cast_data!(enum_data, EnumData, self, item.span);
+        down_cast_data!(enum_data, EnumData, item.span);
         let normalized = enum_data.clone().normalize(&self.tcx);
         if !self.span.filter_generated(Some(normalized.span), item.span) {
             self.dumper.enum_data(item.span, normalized);
@@ -638,7 +638,7 @@ where D: Dump
                     impl_items: &[ast::ImplItem]) {
         let mut has_self_ref = false;
         if let Some(impl_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(impl_data, ImplData, self, item.span);
+            down_cast_data!(impl_data, ImplData, item.span);
             if let Some(ref self_ref) = impl_data.self_ref {
                 has_self_ref = true;
                 if !self.span.filter_generated(Some(self_ref.span), item.span) {
@@ -734,7 +734,7 @@ where D: Dump
     // `item` is the module in question, represented as an item.
     fn process_mod(&mut self, item: &ast::Item) {
         if let Some(mod_data) = self.save_ctxt.get_item_data(item) {
-            down_cast_data!(mod_data, ModData, self, item.span);
+            down_cast_data!(mod_data, ModData, item.span);
             if !self.span.filter_generated(Some(mod_data.span), item.span) {
                 self.dumper.mod_data(mod_data.normalize(&self.tcx));
             }
@@ -750,10 +750,9 @@ where D: Dump
         let path_data = match path_data {
             Some(pd) => pd,
             None => {
-                self.tcx.sess.span_bug(path.span,
-                                       &format!("Unexpected def kind while looking up path in \
-                                                 `{}`",
-                                                self.span.snippet(path.span)))
+                span_bug!(path.span,
+                          "Unexpected def kind while looking up path in `{}`",
+                          self.span.snippet(path.span))
             }
         };
 
@@ -807,8 +806,7 @@ where D: Dump
                 }
             }
             _ => {
-                self.sess.span_bug(path.span,
-                                   &format!("Unexpected data: {:?}", path_data));
+               span_bug!(path.span, "Unexpected data: {:?}", path_data);
             }
         }
 
@@ -844,7 +842,7 @@ where D: Dump
         self.write_sub_paths_truncated(path, false);
 
         if let Some(struct_lit_data) = self.save_ctxt.get_expr_data(ex) {
-            down_cast_data!(struct_lit_data, TypeRefData, self, ex.span);
+            down_cast_data!(struct_lit_data, TypeRefData, ex.span);
             if !self.span.filter_generated(Some(struct_lit_data.span), ex.span) {
                 self.dumper.type_ref(ex.span, struct_lit_data.normalize(&self.tcx));
             }
@@ -869,7 +867,7 @@ where D: Dump
 
     fn process_method_call(&mut self, ex: &ast::Expr, args: &Vec<P<ast::Expr>>) {
         if let Some(mcd) = self.save_ctxt.get_expr_data(ex) {
-            down_cast_data!(mcd, MethodCallData, self, ex.span);
+            down_cast_data!(mcd, MethodCallData, ex.span);
             if !self.span.filter_generated(Some(mcd.span), ex.span) {
                 self.dumper.method_call(ex.span, mcd.normalize(&self.tcx));
             }
@@ -1234,7 +1232,7 @@ impl<'l, 'tcx, 'v, D: Dump + 'l> Visitor<'v> for DumpVisitor<'l, 'tcx, D> {
                 self.visit_expr(&sub_ex);
 
                 if let Some(field_data) = self.save_ctxt.get_expr_data(ex) {
-                    down_cast_data!(field_data, VariableRefData, self, ex.span);
+                    down_cast_data!(field_data, VariableRefData, ex.span);
                     if !self.span.filter_generated(Some(field_data.span), ex.span) {
                         self.dumper.variable_ref(ex.span, field_data.normalize(&self.tcx));
                     }
@@ -1258,9 +1256,9 @@ impl<'l, 'tcx, 'v, D: Dump + 'l> Visitor<'v> for DumpVisitor<'l, 'tcx, D> {
                         }
                     }
                     ty::TyTuple(_) => {}
-                    _ => self.sess.span_bug(ex.span,
-                                            &format!("Expected struct or tuple type, found {:?}",
-                                                     ty)),
+                    _ => span_bug!(ex.span,
+                                   "Expected struct or tuple type, found {:?}",
+                                   ty),
                 }
             }
             ast::ExprKind::Closure(_, ref decl, ref body) => {
@@ -1302,7 +1300,7 @@ impl<'l, 'tcx, 'v, D: Dump + 'l> Visitor<'v> for DumpVisitor<'l, 'tcx, D> {
 
     fn visit_mac(&mut self, mac: &ast::Mac) {
         // These shouldn't exist in the AST at this point, log a span bug.
-        self.sess.span_bug(mac.span, "macro invocation should have been expanded out of AST");
+        span_bug!(mac.span, "macro invocation should have been expanded out of AST");
     }
 
     fn visit_pat(&mut self, p: &ast::Pat) {
@@ -1325,8 +1323,7 @@ impl<'l, 'tcx, 'v, D: Dump + 'l> Visitor<'v> for DumpVisitor<'l, 'tcx, D> {
         for &(id, ref p, immut, ref_kind) in &collector.collected_paths {
             let def_map = self.tcx.def_map.borrow();
             if !def_map.contains_key(&id) {
-                self.sess.span_bug(p.span,
-                                   &format!("def_map has no key for {} in visit_arm", id));
+                span_bug!(p.span, "def_map has no key for {} in visit_arm", id);
             }
             let def = def_map.get(&id).unwrap().full_def();
             match def {
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index f3a7076f955..36b94731e45 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -22,7 +22,7 @@
 #![feature(rustc_private)]
 #![feature(staged_api)]
 
-extern crate rustc;
+#[macro_use] extern crate rustc;
 extern crate rustc_front;
 
 #[macro_use] extern crate log;
@@ -47,7 +47,6 @@ use syntax::visit::{self, Visitor};
 use syntax::print::pprust::ty_to_string;
 
 mod csv_dumper;
-#[macro_use]
 mod data;
 mod dump;
 mod dump_visitor;
@@ -240,7 +239,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             }
             _ => {
                 // FIXME
-                unimplemented!();
+                bug!();
             }
         }
     }
@@ -292,21 +291,19 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                             result
                         }
                         _ => {
-                            self.tcx.sess.span_bug(span,
-                                                   &format!("Container {:?} for method {} not \
-                                                             an impl?",
-                                                            impl_id,
-                                                            id));
+                            span_bug!(span,
+                                      "Container {:?} for method {} not an impl?",
+                                      impl_id,
+                                      id);
                         }
                     }
                 }
                 r => {
-                    self.tcx.sess.span_bug(span,
-                                           &format!("Container {:?} for method {} is not a node \
-                                                     item {:?}",
-                                                    impl_id,
-                                                    id,
-                                                    r));
+                    span_bug!(span,
+                              "Container {:?} for method {} is not a node item {:?}",
+                              impl_id,
+                              id,
+                              r);
                 }
             },
             None => match self.tcx.trait_of_item(self.tcx.map.local_def_id(id)) {
@@ -316,18 +313,17 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                             format!("::{}", self.tcx.item_path_str(def_id))
                         }
                         r => {
-                            self.tcx.sess.span_bug(span,
-                                                   &format!("Could not find container {:?} for \
-                                                             method {}, got {:?}",
-                                                            def_id,
-                                                            id,
-                                                            r));
+                            span_bug!(span,
+                                      "Could not find container {:?} for \
+                                       method {}, got {:?}",
+                                      def_id,
+                                      id,
+                                      r);
                         }
                     }
                 }
                 None => {
-                    self.tcx.sess.span_bug(span,
-                                           &format!("Could not find container for method {}", id));
+                    span_bug!(span, "Could not find container for method {}", id);
                 }
             },
         };
@@ -443,7 +439,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             }
             _ => {
                 // FIXME
-                unimplemented!();
+                bug!();
             }
         }
     }
@@ -451,8 +447,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
         let def_map = self.tcx.def_map.borrow();
         if !def_map.contains_key(&id) {
-            self.tcx.sess.span_bug(path.span,
-                                   &format!("def_map has no key for {} in visit_expr", id));
+            span_bug!(path.span, "def_map has no key for {} in visit_expr", id);
         }
         let def = def_map.get(&id).unwrap().full_def();
         let sub_span = self.span_utils.span_for_last_ident(path.span);
@@ -618,13 +613,12 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
 
     pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
         // FIXME
-        unimplemented!();
+        bug!();
     }
 
     fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
         if !self.tcx.def_map.borrow().contains_key(&ref_id) {
-            self.tcx.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
-                                       ref_id));
+            bug!("def_map has no key for {} in lookup_type_ref", ref_id);
         }
         let def = self.tcx.def_map.borrow().get(&ref_id).unwrap().full_def();
         match def {
diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs
index 4080607eed5..f410d428177 100644
--- a/src/librustc_save_analysis/span_utils.rs
+++ b/src/librustc_save_analysis/span_utils.rs
@@ -223,12 +223,12 @@ impl<'a> SpanUtils<'a> {
         }
         if bracket_count != 0 {
             let loc = self.sess.codemap().lookup_char_pos(span.lo);
-            self.sess.span_bug(span,
-                               &format!("Mis-counted brackets when breaking path? Parsing '{}' \
-                                         in {}, line {}",
-                                        self.snippet(span),
-                                        loc.file.name,
-                                        loc.line));
+            span_bug!(span,
+                      "Mis-counted brackets when breaking path? Parsing '{}' \
+                       in {}, line {}",
+                      self.snippet(span),
+                      loc.file.name,
+                      loc.line);
         }
         if result.is_none() && prev.tok.is_ident() && bracket_count == 0 {
             return self.make_sub_span(span, Some(prev.sp));
@@ -256,12 +256,12 @@ impl<'a> SpanUtils<'a> {
                         return vec!();
                     }
                     let loc = self.sess.codemap().lookup_char_pos(span.lo);
-                    self.sess.span_bug(span,
-                                       &format!("Mis-counted brackets when breaking path? \
-                                                 Parsing '{}' in {}, line {}",
-                                                self.snippet(span),
-                                                loc.file.name,
-                                                loc.line));
+                    span_bug!(span,
+                              "Mis-counted brackets when breaking path? \
+                               Parsing '{}' in {}, line {}",
+                              self.snippet(span),
+                              loc.file.name,
+                              loc.line);
                 }
                 return result
             }
@@ -374,7 +374,7 @@ impl<'a> SpanUtils<'a> {
               loc.line);
         self.err_count.set(self.err_count.get() + 1);
         if self.err_count.get() > 1000 {
-            self.sess.bug("span errors reached 1000, giving up");
+            bug!("span errors reached 1000, giving up");
         }
     }
 
diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs
index f545ba2cbe0..b27929c80c2 100644
--- a/src/librustc_trans/_match.rs
+++ b/src/librustc_trans/_match.rs
@@ -242,7 +242,7 @@ impl<'a> ConstantExpr<'a> {
     fn eq(self, other: ConstantExpr<'a>, tcx: &TyCtxt) -> bool {
         match compare_lit_exprs(tcx, self.0, other.0) {
             Some(result) => result == Ordering::Equal,
-            None => panic!("compare_list_exprs: type mismatch"),
+            None => bug!("compare_list_exprs: type mismatch"),
         }
     }
 }
@@ -828,7 +828,7 @@ impl FailureHandler {
     fn handle_fail(&self, bcx: Block) {
         match *self {
             Infallible =>
-                panic!("attempted to panic in a non-panicking panic handler!"),
+                bug!("attempted to panic in a non-panicking panic handler!"),
             JumpToBasicBlock(basic_block) =>
                 Br(bcx, basic_block, DebugLoc::None),
             Unreachable =>
@@ -939,11 +939,11 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
 
                     compare_str(cx, lhs_data, lhs_len, rhs_data, rhs_len, rhs_t, debug_loc)
                 },
-                _ => cx.sess().bug("only byte strings supported in compare_values"),
+                _ => bug!("only byte strings supported in compare_values"),
             },
-            _ => cx.sess().bug("only string and byte strings supported in compare_values"),
+            _ => bug!("only string and byte strings supported in compare_values"),
         },
-        _ => cx.sess().bug("only scalars, byte strings, and strings supported in compare_values"),
+        _ => bug!("only scalars, byte strings, and strings supported in compare_values"),
     }
 }
 
@@ -986,7 +986,7 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                         Lvalue::new_with_hint("_match::insert_lllocals (match_input)",
                                               bcx, binding_info.id, hint_kind)
                     }
-                    _ => unreachable!(),
+                    _ => bug!(),
                 };
                 let datum = Datum::new(llval, binding_info.ty, lvalue);
                 call_lifetime_start(bcx, llbinding);
@@ -1317,7 +1317,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                             bcx = r.bcx;
                         }
                         _ => {
-                            bcx.sess().bug(
+                            bug!(
                                 "in compile_submatch, expected \
                                  opt.trans() to return a SingleResult")
                         }
diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs
index dd72322997a..6edc26c7009 100644
--- a/src/librustc_trans/abi.rs
+++ b/src/librustc_trans/abi.rs
@@ -218,7 +218,7 @@ impl FnType {
             Rust | RustCall => llvm::CCallConv,
 
             // It's the ABI's job to select this, not us.
-            System => ccx.sess().bug("system abi should be selected elsewhere"),
+            System => bug!("system abi should be selected elsewhere"),
 
             Stdcall => llvm::X86StdcallCallConv,
             Fastcall => llvm::X86FastcallCallConv,
@@ -241,8 +241,8 @@ impl FnType {
                     &tupled_arguments[..]
                 }
                 _ => {
-                    unreachable!("argument to function with \"rust-call\" ABI \
-                                  is not a tuple");
+                    bug!("argument to function with \"rust-call\" ABI \
+                          is not a tuple");
                 }
             }
         } else {
diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs
index 7c190c2ff71..8922aa06182 100644
--- a/src/librustc_trans/adt.rs
+++ b/src/librustc_trans/adt.rs
@@ -302,9 +302,8 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // non-empty body, explicit discriminants should have
             // been rejected by a checker before this point.
             if !cases.iter().enumerate().all(|(i,c)| c.discr == Disr::from(i)) {
-                cx.sess().bug(&format!("non-C-like enum {} with specified \
-                                        discriminants",
-                                       cx.tcx().item_path_str(def.did)));
+                bug!("non-C-like enum {} with specified discriminants",
+                     cx.tcx().item_path_str(def.did));
             }
 
             if cases.len() == 1 {
@@ -430,7 +429,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             General(ity, fields, dtor_to_init_u8(dtor))
         }
-        _ => cx.sess().bug(&format!("adt::represent_type called on non-ADT type: {}", t))
+        _ => bug!("adt::represent_type called on non-ADT type: {}", t)
     }
 }
 
@@ -615,7 +614,7 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
     match hint {
         attr::ReprInt(span, ity) => {
             if !bounds_usable(cx, ity, bounds) {
-                cx.sess().span_bug(span, "representation hint insufficient for discriminant range")
+                span_bug!(span, "representation hint insufficient for discriminant range")
             }
             return ity;
         }
@@ -632,10 +631,10 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
             attempts = choose_shortest;
         },
         attr::ReprPacked => {
-            cx.tcx().sess.bug("range_to_inttype: found ReprPacked on an enum");
+            bug!("range_to_inttype: found ReprPacked on an enum");
         }
         attr::ReprSimd => {
-            cx.tcx().sess.bug("range_to_inttype: found ReprSimd on an enum");
+            bug!("range_to_inttype: found ReprSimd on an enum");
         }
     }
     for &ity in attempts {
@@ -835,7 +834,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                  Type::array(&Type::i64(cx), align_units),
                 a if a.count_ones() == 1 => Type::array(&Type::vector(&Type::i32(cx), a / 4),
                                                               align_units),
-                _ => panic!("unsupported enum alignment: {}", align)
+                _ => bug!("unsupported enum alignment: {}", align)
             };
             assert_eq!(machine::llalign_of_min(cx, fill_ty), align);
             assert_eq!(padded_discr_size % discr_size, 0); // Ensure discr_ty can fill pad evenly
@@ -984,7 +983,7 @@ pub fn trans_case<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr, discr: Disr)
             C_integral(ll_inttype(bcx.ccx(), ity), discr.0, true)
         }
         Univariant(..) => {
-            bcx.ccx().sess().bug("no cases for univariants or structs")
+            bug!("no cases for univariants or structs")
         }
         RawNullablePointer { .. } |
         StructWrappedNullablePointer { .. } => {
@@ -1088,7 +1087,7 @@ pub fn trans_field_ptr_builder<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
     // someday), it will need to return a possibly-new bcx as well.
     match *r {
         CEnum(..) => {
-            bcx.ccx().sess().bug("element access in C-like enum")
+            bug!("element access in C-like enum")
         }
         Univariant(ref st, _dtor) => {
             assert_eq!(discr, Disr(0));
@@ -1279,7 +1278,7 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 
             bcx_next
         }
-        _ => unreachable!()
+        _ => bug!()
     }
 }
 
@@ -1319,7 +1318,7 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
             datum::DatumBlock::new(bcx, expr_datum)
         }
-        _ => bcx.ccx().sess().bug("tried to get drop flag of non-droppable type")
+        _ => bug!("tried to get drop flag of non-droppable type")
     }
 }
 
@@ -1478,7 +1477,7 @@ pub fn const_get_discrim(r: &Repr, val: ValueRef) -> Disr {
         }
         Univariant(..) => Disr(0),
         RawNullablePointer { .. } | StructWrappedNullablePointer { .. } => {
-            unreachable!("const discrim access of non c-like enum")
+            bug!("const discrim access of non c-like enum")
         }
     }
 }
@@ -1488,10 +1487,10 @@ pub fn const_get_discrim(r: &Repr, val: ValueRef) -> Disr {
 ///
 /// (Not to be confused with `common::const_get_elt`, which operates on
 /// raw LLVM-level structs and arrays.)
-pub fn const_get_field(ccx: &CrateContext, r: &Repr, val: ValueRef,
-                       _discr: Disr, ix: usize) -> ValueRef {
+pub fn const_get_field(r: &Repr, val: ValueRef, _discr: Disr,
+                       ix: usize) -> ValueRef {
     match *r {
-        CEnum(..) => ccx.sess().bug("element access in C-like enum const"),
+        CEnum(..) => bug!("element access in C-like enum const"),
         Univariant(..) => const_struct_field(val, ix),
         General(..) => const_struct_field(val, ix + 1),
         RawNullablePointer { .. } => {
diff --git a/src/librustc_trans/assert_dep_graph.rs b/src/librustc_trans/assert_dep_graph.rs
index dcf23039e25..bd98b3950d4 100644
--- a/src/librustc_trans/assert_dep_graph.rs
+++ b/src/librustc_trans/assert_dep_graph.rs
@@ -221,7 +221,7 @@ fn dump_graph(tcx: &TyCtxt) {
             // Expect one of: "-> target", "source -> target", or "source ->".
             let parts: Vec<_> = string.split("->").collect();
             if parts.len() > 2 {
-                panic!("Invalid RUST_DEP_GRAPH_FILTER: expected '[source] -> [target]'");
+                bug!("Invalid RUST_DEP_GRAPH_FILTER: expected '[source] -> [target]'");
             }
             let sources = node_set(&query, &parts[0]);
             let targets = node_set(&query, &parts[1]);
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 062f9482c72..7aef1d912ec 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -187,8 +187,8 @@ pub fn link_binary(sess: &Session,
     let mut out_filenames = Vec::new();
     for &crate_type in sess.crate_types.borrow().iter() {
         if invalid_output_for_target(sess, crate_type) {
-            sess.bug(&format!("invalid output type `{:?}` for target os `{}`",
-                             crate_type, sess.opts.target_triple));
+           bug!("invalid output type `{:?}` for target os `{}`",
+                crate_type, sess.opts.target_triple);
         }
         let out_file = link_binary_output(sess, trans, crate_type, outputs,
                                           crate_name);
@@ -282,7 +282,7 @@ pub fn each_linked_rlib(sess: &Session,
     let fmts = fmts.get(&config::CrateTypeExecutable).or_else(|| {
         fmts.get(&config::CrateTypeStaticlib)
     }).unwrap_or_else(|| {
-        sess.bug("could not find formats for rlibs")
+        bug!("could not find formats for rlibs")
     });
     for (cnum, path) in crates {
         match fmts[cnum as usize - 1] {
@@ -895,7 +895,7 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
         match kind {
             NativeLibraryKind::NativeUnknown => cmd.link_dylib(l),
             NativeLibraryKind::NativeFramework => cmd.link_framework(l),
-            NativeLibraryKind::NativeStatic => unreachable!(),
+            NativeLibraryKind::NativeStatic => bug!(),
         }
     }
 }
@@ -1081,7 +1081,7 @@ fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) {
                 NativeLibraryKind::NativeUnknown => cmd.link_dylib(lib),
                 NativeLibraryKind::NativeFramework => cmd.link_framework(lib),
                 NativeLibraryKind::NativeStatic => {
-                    sess.bug("statics shouldn't be propagated");
+                    bug!("statics shouldn't be propagated");
                 }
             }
         }
diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs
index 29caf93dcd5..c02a482f812 100644
--- a/src/librustc_trans/back/linker.rs
+++ b/src/librustc_trans/back/linker.rs
@@ -271,10 +271,10 @@ impl<'a> Linker for MsvcLinker<'a> {
     }
 
     fn framework_path(&mut self, _path: &Path) {
-        panic!("frameworks are not supported on windows")
+        bug!("frameworks are not supported on windows")
     }
     fn link_framework(&mut self, _framework: &str) {
-        panic!("frameworks are not supported on windows")
+        bug!("frameworks are not supported on windows")
     }
 
     fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs
index ee5282e9881..a458307da40 100644
--- a/src/librustc_trans/back/symbol_names.rs
+++ b/src/librustc_trans/back/symbol_names.rs
@@ -224,8 +224,8 @@ fn exported_name_with_opt_suffix<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 // to be a value or type-def or something in there
                 // *somewhere*
                 ty_def_id.index = key.parent.unwrap_or_else(|| {
-                    panic!("finding type for {:?}, encountered def-id {:?} with no \
-                            parent", def_id, ty_def_id);
+                    bug!("finding type for {:?}, encountered def-id {:?} with no \
+                         parent", def_id, ty_def_id);
                 });
             }
         }
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index 2de650a59be..e6a51eb7c87 100644
--- a/src/librustc_trans/back/write.rs
+++ b/src/librustc_trans/back/write.rs
@@ -113,7 +113,7 @@ impl Emitter for SharedEmitter {
     }
 
     fn custom_emit(&mut self, _sp: &errors::RenderSpan, _msg: &str, _lvl: Level) {
-        panic!("SharedEmitter doesn't support custom_emit");
+        bug!("SharedEmitter doesn't support custom_emit");
     }
 }
 
@@ -159,7 +159,7 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
                                  .cg
                                  .relocation_model));
             sess.abort_if_errors();
-            unreachable!();
+            bug!();
         }
     };
 
@@ -190,7 +190,7 @@ pub fn create_target_machine(sess: &Session) -> TargetMachineRef {
                                  .cg
                                  .code_model));
             sess.abort_if_errors();
-            unreachable!();
+            bug!();
         }
     };
 
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 559ba17e1ae..e5667e06b44 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -227,8 +227,7 @@ pub fn malloc_raw_dyn<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 }
 
 
-pub fn bin_op_to_icmp_predicate(ccx: &CrateContext,
-                                op: hir::BinOp_,
+pub fn bin_op_to_icmp_predicate(op: hir::BinOp_,
                                 signed: bool)
                                 -> llvm::IntPredicate {
     match op {
@@ -239,15 +238,14 @@ pub fn bin_op_to_icmp_predicate(ccx: &CrateContext,
         hir::BiGt => if signed { llvm::IntSGT } else { llvm::IntUGT },
         hir::BiGe => if signed { llvm::IntSGE } else { llvm::IntUGE },
         op => {
-            ccx.sess()
-               .bug(&format!("comparison_op_to_icmp_predicate: expected comparison operator, \
-                              found {:?}",
-                             op));
+            bug!("comparison_op_to_icmp_predicate: expected comparison operator, \
+                  found {:?}",
+                 op)
         }
     }
 }
 
-pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: hir::BinOp_) -> llvm::RealPredicate {
+pub fn bin_op_to_fcmp_predicate(op: hir::BinOp_) -> llvm::RealPredicate {
     match op {
         hir::BiEq => llvm::RealOEQ,
         hir::BiNe => llvm::RealUNE,
@@ -256,10 +254,9 @@ pub fn bin_op_to_fcmp_predicate(ccx: &CrateContext, op: hir::BinOp_) -> llvm::Re
         hir::BiGt => llvm::RealOGT,
         hir::BiGe => llvm::RealOGE,
         op => {
-            ccx.sess()
-               .bug(&format!("comparison_op_to_fcmp_predicate: expected comparison operator, \
-                              found {:?}",
-                             op));
+            bug!("comparison_op_to_fcmp_predicate: expected comparison operator, \
+                  found {:?}",
+                 op);
         }
     }
 }
@@ -291,7 +288,7 @@ pub fn compare_fat_ptrs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 hir::BiLe => (llvm::IntULE, llvm::IntULT),
                 hir::BiGt => (llvm::IntUGT, llvm::IntUGT),
                 hir::BiGe => (llvm::IntUGE, llvm::IntUGT),
-                _ => unreachable!(),
+                _ => bug!(),
             };
 
             let addr_eq = ICmp(bcx, llvm::IntEQ, lhs_addr, rhs_addr, debug_loc);
@@ -302,7 +299,7 @@ pub fn compare_fat_ptrs<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             Or(bcx, addr_strict, addr_eq_extra_op, debug_loc)
         }
         _ => {
-            bcx.tcx().sess.bug("unexpected fat ptr binop");
+            bug!("unexpected fat ptr binop");
         }
     }
 }
@@ -322,19 +319,19 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 hir::BiEq | hir::BiLe | hir::BiGe => return C_bool(bcx.ccx(), true),
                 hir::BiNe | hir::BiLt | hir::BiGt => return C_bool(bcx.ccx(), false),
                 // refinements would be nice
-                _ => bcx.sess().bug("compare_scalar_types: must be a comparison operator"),
+                _ => bug!("compare_scalar_types: must be a comparison operator"),
             }
         }
         ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyBool | ty::TyUint(_) | ty::TyChar => {
             ICmp(bcx,
-                 bin_op_to_icmp_predicate(bcx.ccx(), op, false),
+                 bin_op_to_icmp_predicate(op, false),
                  lhs,
                  rhs,
                  debug_loc)
         }
         ty::TyRawPtr(mt) if common::type_is_sized(bcx.tcx(), mt.ty) => {
             ICmp(bcx,
-                 bin_op_to_icmp_predicate(bcx.ccx(), op, false),
+                 bin_op_to_icmp_predicate(op, false),
                  lhs,
                  rhs,
                  debug_loc)
@@ -356,20 +353,20 @@ pub fn compare_scalar_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         ty::TyInt(_) => {
             ICmp(bcx,
-                 bin_op_to_icmp_predicate(bcx.ccx(), op, true),
+                 bin_op_to_icmp_predicate(op, true),
                  lhs,
                  rhs,
                  debug_loc)
         }
         ty::TyFloat(_) => {
             FCmp(bcx,
-                 bin_op_to_fcmp_predicate(bcx.ccx(), op),
+                 bin_op_to_fcmp_predicate(op),
                  lhs,
                  rhs,
                  debug_loc)
         }
         // Should never get here, because t is scalar.
-        _ => bcx.sess().bug("non-scalar type passed to compare_scalar_types"),
+        _ => bug!("non-scalar type passed to compare_scalar_types"),
     }
 }
 
@@ -383,15 +380,15 @@ pub fn compare_simd_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                       -> ValueRef {
     let signed = match t.sty {
         ty::TyFloat(_) => {
-            let cmp = bin_op_to_fcmp_predicate(bcx.ccx(), op);
+            let cmp = bin_op_to_fcmp_predicate(op);
             return SExt(bcx, FCmp(bcx, cmp, lhs, rhs, debug_loc), ret_ty);
         },
         ty::TyUint(_) => false,
         ty::TyInt(_) => true,
-        _ => bcx.sess().bug("compare_simd_types: invalid SIMD type"),
+        _ => bug!("compare_simd_types: invalid SIMD type"),
     };
 
-    let cmp = bin_op_to_icmp_predicate(bcx.ccx(), op, signed);
+    let cmp = bin_op_to_icmp_predicate(op, signed);
     // LLVM outputs an `< size x i1 >`, so we need to perform a sign extension
     // to get the correctly sized type. This will compile to a single instruction
     // once the IR is converted to assembly if the SIMD instruction is supported
@@ -578,9 +575,9 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
             consts::ptrcast(meth::get_vtable(ccx, trait_ref),
                             Type::vtable_ptr(ccx))
         }
-        _ => ccx.sess().bug(&format!("unsized_info: invalid unsizing {:?} -> {:?}",
+        _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}",
                                      source,
-                                     target)),
+                                     target),
     }
 }
 
@@ -604,7 +601,7 @@ pub fn unsize_thin_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             (PointerCast(bcx, src, ptr_ty),
              unsized_info(bcx.ccx(), a, b, None))
         }
-        _ => bcx.sess().bug("unsize_thin_ptr: called on bad types"),
+        _ => bug!("unsize_thin_ptr: called on bad types"),
     }
 }
 
@@ -638,12 +635,12 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let src_repr = adt::represent_type(bcx.ccx(), src_ty);
             let src_fields = match &*src_repr {
                 &adt::Repr::Univariant(ref s, _) => &s.fields,
-                _ => bcx.sess().bug("struct has non-univariant repr"),
+                _ => bug!("struct has non-univariant repr"),
             };
             let dst_repr = adt::represent_type(bcx.ccx(), dst_ty);
             let dst_fields = match &*dst_repr {
                 &adt::Repr::Univariant(ref s, _) => &s.fields,
-                _ => bcx.sess().bug("struct has non-univariant repr"),
+                _ => bug!("struct has non-univariant repr"),
             };
 
             let src = adt::MaybeSizedValue::sized(src);
@@ -664,9 +661,9 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        _ => bcx.sess().bug(&format!("coerce_unsized_into: invalid coercion {:?} -> {:?}",
-                                     src_ty,
-                                     dst_ty)),
+        _ => bug!("coerce_unsized_into: invalid coercion {:?} -> {:?}",
+                  src_ty,
+                  dst_ty),
     }
 }
 
@@ -689,8 +686,7 @@ pub fn custom_coerce_unsize_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
             ccx.tcx().custom_coerce_unsized_kind(impl_def_id)
         }
         vtable => {
-            ccx.sess().bug(&format!("invalid CoerceUnsized vtable: {:?}",
-                                    vtable));
+            bug!("invalid CoerceUnsized vtable: {:?}", vtable);
         }
     }
 }
@@ -758,7 +754,7 @@ pub fn llty_and_min_for_signed_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
             };
             (llty, min)
         }
-        _ => unreachable!(),
+        _ => bug!(),
     }
 }
 
@@ -798,7 +794,7 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
             (res, false)
         }
         _ => {
-            cx.sess().bug(&format!("fail-if-zero on unexpected type: {}", rhs_t));
+            bug!("fail-if-zero on unexpected type: {}", rhs_t);
         }
     };
     let bcx = with_cond(cx, is_zero, |bcx| {
@@ -1323,15 +1319,15 @@ fn build_cfg(tcx: &TyCtxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
                 hir::ItemFn(_, _, _, _, _, ref blk) => {
                     blk
                 }
-                _ => tcx.sess.bug("unexpected item variant in has_nested_returns"),
+                _ => bug!("unexpected item variant in has_nested_returns"),
             }
         }
         Some(hir_map::NodeTraitItem(trait_item)) => {
             match trait_item.node {
                 hir::MethodTraitItem(_, Some(ref body)) => body,
                 _ => {
-                    tcx.sess.bug("unexpected variant: trait item other than a provided method in \
-                                  has_nested_returns")
+                    bug!("unexpected variant: trait item other than a provided method in \
+                          has_nested_returns")
                 }
             }
         }
@@ -1339,14 +1335,14 @@ fn build_cfg(tcx: &TyCtxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
             match impl_item.node {
                 hir::ImplItemKind::Method(_, ref body) => body,
                 _ => {
-                    tcx.sess.bug("unexpected variant: non-method impl item in has_nested_returns")
+                    bug!("unexpected variant: non-method impl item in has_nested_returns")
                 }
             }
         }
         Some(hir_map::NodeExpr(e)) => {
             match e.node {
                 hir::ExprClosure(_, _, ref blk) => blk,
-                _ => tcx.sess.bug("unexpected expr variant in has_nested_returns"),
+                _ => bug!("unexpected expr variant in has_nested_returns"),
             }
         }
         Some(hir_map::NodeVariant(..)) |
@@ -1355,8 +1351,8 @@ fn build_cfg(tcx: &TyCtxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
         // glue, shims, etc
         None if id == ast::DUMMY_NODE_ID => return (ast::DUMMY_NODE_ID, None),
 
-        _ => tcx.sess.bug(&format!("unexpected variant in has_nested_returns: {}",
-                                   tcx.map.path_to_string(id))),
+        _ => bug!("unexpected variant in has_nested_returns: {}",
+                  tcx.map.path_to_string(id)),
     };
 
     (blk.id, Some(cfg::CFG::new(tcx, blk)))
@@ -1675,7 +1671,7 @@ impl<'blk, 'tcx> FunctionContext<'blk, 'tcx> {
                 // FIXME(pcwalton): Reduce the amount of code bloat this is responsible for.
                 let tupled_arg_tys = match arg_ty.sty {
                     ty::TyTuple(ref tys) => tys,
-                    _ => unreachable!("last argument of `rust-call` fn isn't a tuple?!")
+                    _ => bug!("last argument of `rust-call` fn isn't a tuple?!")
                 };
 
                 unpack_datum!(bcx, datum::lvalue_scratch_datum(bcx,
@@ -1978,7 +1974,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                       expr::SaveIn(llresult),
                                       debug_loc);
             }
-            _ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor"),
+            _ => bug!("expected expr as arguments for variant/struct tuple constructor"),
         }
     } else {
         // Just eval all the expressions (if any). Since expressions in Rust can have arbitrary
@@ -2381,7 +2377,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext, sp: Span, main_llfn: ValueRef) {
                       .help("did you use #[no_mangle] on `fn main`? Use #[start] instead")
                       .emit();
             ccx.sess().abort_if_errors();
-            panic!();
+            bug!();
         }
         let llfn = declare::declare_cfn(ccx, "main", llfty);
 
@@ -2734,7 +2730,7 @@ pub fn trans_crate<'tcx>(tcx: &TyCtxt<'tcx>,
         });
 
         if POISONED {
-            tcx.sess.bug("couldn't enable multi-threaded LLVM");
+            bug!("couldn't enable multi-threaded LLVM");
         }
     }
 
diff --git a/src/librustc_trans/build.rs b/src/librustc_trans/build.rs
index 0ce7fdb8b6d..0185d158762 100644
--- a/src/librustc_trans/build.rs
+++ b/src/librustc_trans/build.rs
@@ -32,7 +32,7 @@ pub fn terminate(cx: Block, _: &str) {
 
 pub fn check_not_terminated(cx: Block) {
     if cx.terminated.get() {
-        panic!("already terminated!");
+        bug!("already terminated!");
     }
 }
 
diff --git a/src/librustc_trans/builder.rs b/src/librustc_trans/builder.rs
index 55f65d29bfd..92fb342497b 100644
--- a/src/librustc_trans/builder.rs
+++ b/src/librustc_trans/builder.rs
@@ -871,12 +871,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             .zip(args.iter().map(|&v| val_ty(v)));
         for (i, (expected_ty, actual_ty)) in iter.enumerate() {
             if expected_ty != actual_ty {
-                self.ccx.sess().bug(
-                    &format!(
-                        "Type mismatch in function call of {:?}. \
-                         Expected {:?} for param {}, got {:?}",
-                        Value(llfn),
-                        expected_ty, i, actual_ty));
+                bug!("Type mismatch in function call of {:?}. \
+                      Expected {:?} for param {}, got {:?}",
+                     Value(llfn),
+                     expected_ty, i, actual_ty);
 
             }
         }
diff --git a/src/librustc_trans/cabi_aarch64.rs b/src/librustc_trans/cabi_aarch64.rs
index b2929d118a6..4903af2a6ff 100644
--- a/src/librustc_trans/cabi_aarch64.rs
+++ b/src/librustc_trans/cabi_aarch64.rs
@@ -49,7 +49,7 @@ fn ty_align(ty: Type) -> usize {
             let elt = ty.element_type();
             ty_align(elt) * len
         }
-        _ => panic!("ty_align: unhandled type")
+        _ => bug!("ty_align: unhandled type")
     }
 }
 
@@ -81,7 +81,7 @@ fn ty_size(ty: Type) -> usize {
             let eltsz = ty_size(elt);
             len * eltsz
         }
-        _ => panic!("ty_size: unhandled type")
+        _ => bug!("ty_size: unhandled type")
     }
 }
 
diff --git a/src/librustc_trans/cabi_arm.rs b/src/librustc_trans/cabi_arm.rs
index 5dbcf1ef86e..35099399e31 100644
--- a/src/librustc_trans/cabi_arm.rs
+++ b/src/librustc_trans/cabi_arm.rs
@@ -56,7 +56,7 @@ fn general_ty_align(ty: Type) -> usize {
             let elt = ty.element_type();
             general_ty_align(elt) * len
         }
-        _ => panic!("ty_align: unhandled type")
+        _ => bug!("ty_align: unhandled type")
     }
 }
 
@@ -90,7 +90,7 @@ fn ios_ty_align(ty: Type) -> usize {
             let elt = ty.element_type();
             ios_ty_align(elt) * len
         }
-        _ => panic!("ty_align: unhandled type")
+        _ => bug!("ty_align: unhandled type")
     }
 }
 
@@ -125,7 +125,7 @@ fn ty_size(ty: Type, align_fn: TyAlignFn) -> usize {
             let eltsz = ty_size(elt, align_fn);
             len * eltsz
         }
-        _ => panic!("ty_size: unhandled type")
+        _ => bug!("ty_size: unhandled type")
     }
 }
 
diff --git a/src/librustc_trans/cabi_mips.rs b/src/librustc_trans/cabi_mips.rs
index d0fce01ce73..be9d4cad1db 100644
--- a/src/librustc_trans/cabi_mips.rs
+++ b/src/librustc_trans/cabi_mips.rs
@@ -50,7 +50,7 @@ fn ty_align(ty: Type) -> usize {
             let elt = ty.element_type();
             ty_align(elt) * len
         }
-        _ => panic!("ty_align: unhandled type")
+        _ => bug!("ty_align: unhandled type")
     }
 }
 
@@ -82,7 +82,7 @@ fn ty_size(ty: Type) -> usize {
             let eltsz = ty_size(elt);
             len * eltsz
         }
-        _ => panic!("ty_size: unhandled type")
+        _ => bug!("ty_size: unhandled type")
     }
 }
 
diff --git a/src/librustc_trans/cabi_powerpc.rs b/src/librustc_trans/cabi_powerpc.rs
index c9751aa25c1..d118cc86f24 100644
--- a/src/librustc_trans/cabi_powerpc.rs
+++ b/src/librustc_trans/cabi_powerpc.rs
@@ -48,7 +48,7 @@ fn ty_align(ty: Type) -> usize {
             let elt = ty.element_type();
             ty_align(elt)
         }
-        _ => panic!("ty_size: unhandled type")
+        _ => bug!("ty_size: unhandled type")
     }
 }
 
@@ -78,7 +78,7 @@ fn ty_size(ty: Type) -> usize {
             let eltsz = ty_size(elt);
             len * eltsz
         }
-        _ => panic!("ty_size: unhandled type")
+        _ => bug!("ty_size: unhandled type")
     }
 }
 
diff --git a/src/librustc_trans/cabi_powerpc64.rs b/src/librustc_trans/cabi_powerpc64.rs
index 7e7033b4686..7bc41d26f8b 100644
--- a/src/librustc_trans/cabi_powerpc64.rs
+++ b/src/librustc_trans/cabi_powerpc64.rs
@@ -49,7 +49,7 @@ fn ty_align(ty: Type) -> usize {
             let elt = ty.element_type();
             ty_align(elt)
         }
-        _ => panic!("ty_align: unhandled type")
+        _ => bug!("ty_align: unhandled type")
     }
 }
 
@@ -75,7 +75,7 @@ fn ty_size(ty: Type) -> usize {
             let eltsz = ty_size(elt);
             len * eltsz
         }
-        _ => panic!("ty_size: unhandled type")
+        _ => bug!("ty_size: unhandled type")
     }
 }
 
diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs
index a08d9fb5b40..e9e9e266c77 100644
--- a/src/librustc_trans/cabi_x86_64.rs
+++ b/src/librustc_trans/cabi_x86_64.rs
@@ -112,7 +112,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
                 let elt = ty.element_type();
                 ty_align(elt) * len
             }
-            _ => panic!("ty_align: unhandled type")
+            _ => bug!("ty_align: unhandled type")
         }
     }
 
@@ -144,7 +144,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
                 len * eltsz
             }
 
-            _ => panic!("ty_size: unhandled type")
+            _ => bug!("ty_size: unhandled type")
         }
     }
 
@@ -255,7 +255,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
                     Integer => SSEInt(elt.int_width()),
                     Float => SSEFv,
                     Double => SSEDv,
-                    _ => panic!("classify: unhandled vector element type")
+                    _ => bug!("classify: unhandled vector element type")
                 };
 
                 let mut i = 0;
@@ -268,7 +268,7 @@ fn classify_ty(ty: Type) -> Vec<RegClass> {
                     i += 1;
                 }
             }
-            _ => panic!("classify: unhandled type")
+            _ => bug!("classify: unhandled type")
         }
     }
 
@@ -357,7 +357,7 @@ fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
                                 "llreg_ty: unsupported SSEInt width {}", bits);
                         (64 / bits, Type::ix(ccx, bits))
                     }
-                    _ => unreachable!(),
+                    _ => bug!(),
                 };
                 let vec_len = llvec_len(&cls[i + 1..]);
                 let vec_ty = Type::vector(&elt_ty, vec_len as u64 * elts_per_word);
@@ -371,7 +371,7 @@ fn llreg_ty(ccx: &CrateContext, cls: &[RegClass]) -> Type {
             SSEDs => {
                 tys.push(Type::f64(ccx));
             }
-            _ => panic!("llregtype: unhandled class")
+            _ => bug!("llregtype: unhandled class")
         }
         i += 1;
     }
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index d3c2a895379..a323d63adae 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -184,8 +184,8 @@ impl<'tcx> Callee<'tcx> {
                 let method_ty = def_ty(tcx, def_id, substs);
                 let fn_ptr_ty = match method_ty.sty {
                     ty::TyFnDef(_, _, fty) => tcx.mk_ty(ty::TyFnPtr(fty)),
-                    _ => unreachable!("expected fn item type, found {}",
-                                      method_ty)
+                    _ => bug!("expected fn item type, found {}",
+                              method_ty)
                 };
                 Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
             }
@@ -196,8 +196,8 @@ impl<'tcx> Callee<'tcx> {
                 let method_ty = def_ty(tcx, def_id, substs);
                 let fn_ptr_ty = match method_ty.sty {
                     ty::TyFnDef(_, _, fty) => tcx.mk_ty(ty::TyFnPtr(fty)),
-                    _ => unreachable!("expected fn item type, found {}",
-                                      method_ty)
+                    _ => bug!("expected fn item type, found {}",
+                              method_ty)
                 };
                 Callee::ptr(immediate_rvalue(llfn, fn_ptr_ty))
             }
@@ -209,7 +209,7 @@ impl<'tcx> Callee<'tcx> {
                 }
             }
             vtable => {
-                unreachable!("resolved vtable bad vtable {:?} in trans", vtable);
+                bug!("resolved vtable bad vtable {:?} in trans", vtable);
             }
         }
     }
@@ -269,9 +269,9 @@ impl<'tcx> Callee<'tcx> {
                 ty::TyFnDef(def_id, substs, _) => {
                     return get_fn(ccx, def_id, substs);
                 }
-                _ => unreachable!("expected fn item type, found {}", self.ty)
+                _ => bug!("expected fn item type, found {}", self.ty)
             },
-            Intrinsic => unreachable!("intrinsic {} getting reified", self.ty)
+            Intrinsic => bug!("intrinsic {} getting reified", self.ty)
         }
     }
 }
@@ -356,8 +356,8 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
                                     ref sig }) => sig,
 
         _ => {
-            tcx.sess.bug(&format!("trans_fn_pointer_shim invoked on invalid type: {}",
-                                    bare_fn_ty));
+            bug!("trans_fn_pointer_shim invoked on invalid type: {}",
+                 bare_fn_ty);
         }
     };
     let sig = tcx.erase_late_bound_regions(sig);
@@ -481,7 +481,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 // Create a fn pointer with the substituted signature.
                 tcx.mk_ty(ty::TyFnPtr(fty))
             }
-            _ => unreachable!("expected fn item type, found {}", fn_ty)
+            _ => bug!("expected fn item type, found {}", fn_ty)
         };
         assert_eq!(type_of::type_of(ccx, fn_ptr_ty), common::val_ty(val));
         return immediate_rvalue(val, fn_ptr_ty);
@@ -494,7 +494,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             // Create a fn pointer with the normalized signature.
             tcx.mk_fn_ptr(infer::normalize_associated_type(tcx, fty))
         }
-        _ => unreachable!("expected fn item type, found {}", ty)
+        _ => bug!("expected fn item type, found {}", ty)
     };
 
     let instance = Instance::mono(ccx.tcx(), def_id);
@@ -537,7 +537,7 @@ fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
 
         ref variant => {
-            ccx.sess().bug(&format!("get_fn: unexpected variant: {:?}", variant))
+            bug!("get_fn: unexpected variant: {:?}", variant)
         }
     };
 
@@ -689,7 +689,7 @@ fn trans_call_inner<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
     let llfn = match callee {
         Fn(f) => f,
-        _ => unreachable!("expected fn pointer callee, found {:?}", callee)
+        _ => bug!("expected fn pointer callee, found {:?}", callee)
     };
 
     let (llret, mut bcx) = base::invoke(bcx, llfn, &llargs, debug_loc);
@@ -830,8 +830,8 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
             }
         }
         _ => {
-            bcx.sess().span_bug(tuple_expr.span,
-                                "argument to `.call()` wasn't a tuple?!")
+            span_bug!(tuple_expr.span,
+                      "argument to `.call()` wasn't a tuple?!")
         }
     };
 
diff --git a/src/librustc_trans/cleanup.rs b/src/librustc_trans/cleanup.rs
index 3a8dc144f9c..514e6bda594 100644
--- a/src/librustc_trans/cleanup.rs
+++ b/src/librustc_trans/cleanup.rs
@@ -378,7 +378,7 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
                 return id;
             }
         }
-        self.ccx.sess().bug("no loop scope found");
+        bug!("no loop scope found");
     }
 
     /// Returns a block to branch to which will perform all pending cleanups and
@@ -568,9 +568,8 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
             }
         }
 
-        self.ccx.sess().bug(
-            &format!("no cleanup scope {} found",
-                    self.ccx.tcx().map.node_to_string(cleanup_scope)));
+        bug!("no cleanup scope {} found",
+             self.ccx.tcx().map.node_to_string(cleanup_scope));
     }
 
     /// Schedules a cleanup to occur in the top-most scope, which must be a temporary scope.
@@ -763,9 +762,7 @@ impl<'blk, 'tcx> CleanupHelperMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx
                     }
 
                     LoopExit(id, _) => {
-                        self.ccx.sess().bug(&format!(
-                                "cannot exit from scope {}, \
-                                not in scope", id));
+                        bug!("cannot exit from scope {}, not in scope", id);
                     }
                 }
             }
@@ -1189,8 +1186,7 @@ pub fn temporary_scope(tcx: &TyCtxt,
             r
         }
         None => {
-            tcx.sess.bug(&format!("no temporary scope available for expr {}",
-                                 id))
+            bug!("no temporary scope available for expr {}", id)
         }
     }
 }
diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs
index 44b4f256082..cb94c9dfeb8 100644
--- a/src/librustc_trans/closure.rs
+++ b/src/librustc_trans/closure.rs
@@ -297,7 +297,6 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
     let llfn_closure_kind = ccx.tcx().closure_kind(closure_def_id);
 
     let _icx = push_ctxt("trans_closure_adapter_shim");
-    let tcx = ccx.tcx();
 
     debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \
            trait_closure_kind={:?}, llfn={:?})",
@@ -329,9 +328,9 @@ pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
             trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn)
         }
         _ => {
-            tcx.sess.bug(&format!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
-                                  llfn_closure_kind,
-                                  trait_closure_kind));
+            bug!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
+                 llfn_closure_kind,
+                 trait_closure_kind);
         }
     }
 }
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 7c5f784216a..1c18f3ca393 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -597,7 +597,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         let substs = match fulfill_obligation(ccx, DUMMY_SP, trait_ref) {
             traits::VtableImpl(data) => data.substs,
-            _ => unreachable!()
+            _ => bug!()
         };
 
         if can_have_local_instance(ccx, destructor_did) {
@@ -665,7 +665,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ty::TyParam(_)      |
         ty::TyInfer(_)      |
         ty::TyError         => {
-            ccx.sess().bug("encountered unexpected type");
+            bug!("encountered unexpected type");
         }
     }
 }
@@ -701,7 +701,7 @@ fn do_static_dispatch<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     }
                 }
             }
-            _ => unreachable!()
+            _ => bug!()
         }
     } else {
         debug!(" => regular function");
@@ -760,7 +760,7 @@ fn do_static_trait_method_dispatch<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             None
         }
         _ => {
-            tcx.sess.bug(&format!("static call to invalid vtable: {:?}", vtbl))
+            bug!("static call to invalid vtable: {:?}", vtbl)
         }
     }
 }
@@ -845,10 +845,9 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                            target_fields[coerce_index].ty(ccx.tcx(),
                                                                           target_substs))
         }
-        _ => ccx.sess()
-                .bug(&format!("find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}",
-                               source_ty,
-                               target_ty))
+        _ => bug!("find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}",
+                  source_ty,
+                  target_ty)
     }
 }
 
@@ -1019,7 +1018,7 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
                         generics.is_type_parameterized()
                     }
                     _ => {
-                        unreachable!()
+                        bug!()
                     }
                 };
 
@@ -1101,7 +1100,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             }
         }
         _ => {
-            unreachable!()
+            bug!()
         }
     }
 }
@@ -1252,8 +1251,8 @@ pub fn push_unique_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyInfer(_) |
         ty::TyProjection(..) |
         ty::TyParam(_) => {
-            cx.sess().bug(&format!("debuginfo: Trying to create type name for \
-                unexpected type: {:?}", t));
+            bug!("debuginfo: Trying to create type name for \
+                  unexpected type: {:?}", t);
         }
     }
 }
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index c5d54e30f13..589e6f3266e 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -194,9 +194,7 @@ impl<'tcx> VariantInfo<'tcx> {
             }
 
             _ => {
-                tcx.sess.bug(&format!(
-                    "cannot get field types from the type {:?}",
-                    ty));
+                bug!("cannot get field types from the type {:?}", ty);
             }
         }
     }
@@ -209,7 +207,7 @@ impl<'tcx> VariantInfo<'tcx> {
 
     pub fn field_index(&self, name: ast::Name) -> usize {
         self.fields.iter().position(|&Field(n,_)| n == name).unwrap_or_else(|| {
-            panic!("unknown field `{}`", name)
+            bug!("unknown field `{}`", name)
         })
     }
 }
@@ -596,8 +594,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
         match self.tcx().def_map.borrow().get(&nid) {
             Some(v) => v.full_def(),
             None => {
-                self.tcx().sess.bug(&format!(
-                    "no def associated with node id {}", nid));
+                bug!("no def associated with node id {}", nid);
             }
         }
     }
@@ -910,7 +907,7 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va
         let gsym = token::gensym("str");
         let sym = format!("str{}", gsym.0);
         let g = declare::define_global(cx, &sym[..], val_ty(sc)).unwrap_or_else(||{
-            cx.sess().bug(&format!("symbol `{}` is already defined", sym));
+            bug!("symbol `{}` is already defined", sym);
         });
         llvm::LLVMSetInitializer(g, sc);
         llvm::LLVMSetGlobalConstant(g, True);
@@ -1102,11 +1099,11 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 "reached the recursion limit during monomorphization (selection ambiguity)");
         }
         Err(e) => {
-            tcx.sess.span_bug(
+            span_bug!(
                 span,
-                &format!("Encountered error `{:?}` selecting `{:?}` during trans",
-                        e,
-                        trait_ref))
+                "Encountered error `{:?}` selecting `{:?}` during trans",
+                e,
+                trait_ref)
         }
     };
 
@@ -1194,7 +1191,7 @@ pub fn inlined_variant_def<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         inlined_vid_def_id == v.did ||
             ccx.external().borrow().get(&v.did) == Some(&Some(inlined_vid))
     }).unwrap_or_else(|| {
-        ccx.sess().bug(&format!("no variant for {:?}::{}", adt_def, inlined_vid))
+        bug!("no variant for {:?}::{}", adt_def, inlined_vid)
     })
 }
 
@@ -1255,6 +1252,6 @@ pub fn shift_mask_val<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let mask = shift_mask_val(bcx, llty.element_type(), mask_llty.element_type(), invert);
             build::VectorSplat(bcx, mask_llty.vector_length(), mask)
         },
-        _ => panic!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
+        _ => bug!("shift_mask_val: expected Integer or Vector, found {:?}", kind),
     }
 }
diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs
index 555c12807ba..3e516c0eec4 100644
--- a/src/librustc_trans/consts.rs
+++ b/src/librustc_trans/consts.rs
@@ -75,10 +75,10 @@ pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &ast::Lit)
                 ty::TyUint(t) => {
                     C_integral(Type::uint_from_ty(cx, t), i as u64, false)
                 }
-                _ => cx.sess().span_bug(lit.span,
-                        &format!("integer literal has type {:?} (expected int \
-                                 or usize)",
-                                lit_int_ty))
+                _ => span_bug!(lit.span,
+                        "integer literal has type {:?} (expected int \
+                         or usize)",
+                        lit_int_ty)
             }
         }
         LitKind::Float(ref fs, t) => {
@@ -91,7 +91,7 @@ pub fn const_lit(cx: &CrateContext, e: &hir::Expr, lit: &ast::Lit)
                     C_floating(&fs, Type::float_from_ty(cx, t))
                 }
                 _ => {
-                    cx.sess().span_bug(lit.span,
+                    span_bug!(lit.span,
                         "floating point literal doesn't have the right type");
                 }
             }
@@ -121,7 +121,7 @@ fn addr_of_mut(ccx: &CrateContext,
         let gsym = token::gensym("_");
         let name = format!("{}{}", kind, gsym.0);
         let gv = declare::define_global(ccx, &name[..], val_ty(cv)).unwrap_or_else(||{
-            ccx.sess().bug(&format!("symbol `{}` is already defined", name));
+            bug!("symbol `{}` is already defined", name);
         });
         llvm::LLVMSetInitializer(gv, cv);
         llvm::LLVMSetAlignment(gv, align);
@@ -186,8 +186,7 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
         }
         None => {
-            cx.sess().bug(&format!("unexpected dereferenceable type {:?}",
-                                   ty))
+            bug!("unexpected dereferenceable type {:?}", ty)
         }
     }
 }
@@ -232,7 +231,7 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     match lookup_const_by_id(ccx.tcx(), def_id, Some(substs)) {
         Some((ref expr, _ty)) => expr,
         None => {
-            ccx.sess().span_bug(ref_expr.span, "constant item not found")
+            span_bug!(ref_expr.span, "constant item not found")
         }
     }
 }
@@ -357,7 +356,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     llconst = Callee::def(cx, def_id, substs).reify(cx).val;
                 }
                 _ => {
-                    unreachable!("{} cannot be reified to a fn ptr", ety)
+                    bug!("{} cannot be reified to a fn ptr", ety)
                 }
             }
         }
@@ -441,9 +440,9 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             llvm::LLVMDumpValue(llconst);
             llvm::LLVMDumpValue(C_undef(llty));
         }
-        cx.sess().bug(&format!("const {:?} of type {:?} has size {} instead of {}",
-                         e, ety_adjusted,
-                         csize, tsize));
+        bug!("const {:?} of type {:?} has size {} instead of {}",
+             e, ety_adjusted,
+             csize, tsize);
     }
     Ok((llconst, ety_adjusted))
 }
@@ -550,7 +549,7 @@ fn const_err(cx: &CrateContext,
 fn check_binary_expr_validity(cx: &CrateContext, e: &hir::Expr, t: Ty,
                               te1: ValueRef, te2: ValueRef,
                               trueconst: TrueConst) -> Result<(), ConstEvalFailure> {
-    let b = if let hir::ExprBinary(b, _, _) = e.node { b } else { unreachable!() };
+    let b = if let hir::ExprBinary(b, _, _) = e.node { b } else { bug!() };
     let (lhs, rhs) = match (to_const_int(te1, t, cx.tcx()), to_const_int(te2, t, cx.tcx())) {
         (Some(v1), Some(v2)) => (v1, v2),
         _ => return Ok(()),
@@ -642,10 +641,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 },
                 hir::BiEq | hir::BiNe | hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe => {
                     if is_float {
-                        let cmp = base::bin_op_to_fcmp_predicate(cx, b.node);
+                        let cmp = base::bin_op_to_fcmp_predicate(b.node);
                         ConstFCmp(cmp, te1, te2)
                     } else {
-                        let cmp = base::bin_op_to_icmp_predicate(cx, b.node, signed);
+                        let cmp = base::bin_op_to_icmp_predicate(b.node, signed);
                         ConstICmp(cmp, te1, te2)
                     }
                 },
@@ -669,13 +668,13 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let brepr = adt::represent_type(cx, bt);
             let vinfo = VariantInfo::from_ty(cx.tcx(), bt, None);
             let ix = vinfo.field_index(field.node);
-            adt::const_get_field(cx, &brepr, bv, vinfo.discr, ix)
+            adt::const_get_field(&brepr, bv, vinfo.discr, ix)
         },
         hir::ExprTupField(ref base, idx) => {
             let (bv, bt) = const_expr(cx, &base, param_substs, fn_args, trueconst)?;
             let brepr = adt::represent_type(cx, bt);
             let vinfo = VariantInfo::from_ty(cx.tcx(), bt, None);
-            adt::const_get_field(cx, &brepr, bv, vinfo.discr, idx.node)
+            adt::const_get_field(&brepr, bv, vinfo.discr, idx.node)
         },
         hir::ExprIndex(ref base, ref index) => {
             let (bv, bt) = const_expr(cx, &base, param_substs, fn_args, trueconst)?;
@@ -683,7 +682,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let iv = if let Some(iv) = const_to_opt_uint(iv) {
                 iv
             } else {
-                cx.sess().span_bug(index.span, "index is not an integer-constant expression");
+                span_bug!(index.span, "index is not an integer-constant expression");
             };
             let (arr, len) = match bt.sty {
                 ty::TyArray(_, u) => (bv, C_uint(cx, u)),
@@ -695,15 +694,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     ty::TyArray(_, u) => {
                         (load_const(cx, bv, mt.ty), C_uint(cx, u))
                     },
-                    _ => cx.sess().span_bug(base.span,
-                                            &format!("index-expr base must be a vector \
-                                                      or string type, found {:?}",
-                                                     bt)),
+                    _ => span_bug!(base.span,
+                                   "index-expr base must be a vector \
+                                    or string type, found {:?}",
+                                   bt),
                 },
-                _ => cx.sess().span_bug(base.span,
-                                        &format!("index-expr base must be a vector \
-                                                  or string type, found {:?}",
-                                                 bt)),
+                _ => span_bug!(base.span,
+                               "index-expr base must be a vector \
+                                or string type, found {:?}",
+                               bt),
             };
 
             let len = unsafe { llvm::LLVMConstIntGetZExtValue(len) as u64 };
@@ -784,8 +783,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                   llvm::LLVMConstPtrToInt(v, llty.to_ref())
                 },
                 _ => {
-                  cx.sess().impossible_case(e.span,
-                                            "bad combination of types for cast")
+                  span_bug!(e.span, "bad combination of types for cast")
                 },
             } } // unsafe { match ( ... ) {
         },
@@ -845,8 +843,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     (Some(ref f), _) => {
                         const_expr(cx, &f.expr, param_substs, fn_args, trueconst).map(|(l, _)| l)
                     },
-                    (_, Some((bv, _))) => Ok(adt::const_get_field(cx, &repr, bv, discr, ix)),
-                    (_, None) => cx.sess().span_bug(e.span, "missing struct field"),
+                    (_, Some((bv, _))) => Ok(adt::const_get_field(&repr, bv, discr, ix)),
+                    (_, None) => span_bug!(e.span, "missing struct field"),
                 }
             })
             .collect::<Vec<Result<_, ConstEvalFailure>>>()
@@ -900,7 +898,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     if let Some(val) = fn_args.and_then(|args| args.get(&id).cloned()) {
                         val
                     } else {
-                        cx.sess().span_bug(e.span, "const fn argument not found")
+                        span_bug!(e.span, "const fn argument not found")
                     }
                 }
                 Def::Fn(..) | Def::Method(..) => C_nil(cx),
@@ -917,15 +915,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         }
                         ty::VariantKind::Tuple => C_nil(cx),
                         ty::VariantKind::Struct => {
-                            cx.sess().span_bug(e.span, "path-expr refers to a dict variant!")
+                            span_bug!(e.span, "path-expr refers to a dict variant!")
                         }
                     }
                 }
                 // Unit struct or ctor.
                 Def::Struct(..) => C_null(type_of::type_of(cx, ety)),
                 _ => {
-                    cx.sess().span_bug(e.span, "expected a const, fn, struct, \
-                                                or variant def")
+                    span_bug!(e.span, "expected a const, fn, struct, \
+                                       or variant def")
                 }
             }
         },
@@ -969,7 +967,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                      Disr::from(vinfo.disr_val),
                                      &arg_vals[..])
                 }
-                _ => cx.sess().span_bug(e.span, "expected a struct, variant, or const fn def"),
+                _ => span_bug!(e.span, "expected a struct, variant, or const fn def"),
             }
         },
         hir::ExprMethodCall(_, _, ref args) => {
@@ -1003,14 +1001,14 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                                 substs);
                 }
                 _ =>
-                    cx.sess().span_bug(
+                    span_bug!(
                         e.span,
-                        &format!("bad type for closure expr: {:?}", ety))
+                        "bad type for closure expr: {:?}", ety)
             }
             C_null(type_of::type_of(cx, ety))
         },
-        _ => cx.sess().span_bug(e.span,
-                                "bad constant expression type in consts::const_expr"),
+        _ => span_bug!(e.span,
+                       "bad constant expression type in consts::const_expr"),
     })
 }
 
@@ -1105,7 +1103,7 @@ pub fn get_static<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, def_id: DefId)
                 g
             }
 
-            item => unreachable!("get_static: expected static, found {:?}", item)
+            item => bug!("get_static: expected static, found {:?}", item)
         }
     } else {
         // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index dcf96cfa814..3574883c5f5 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -596,7 +596,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         }
         match declare_intrinsic(self, key) {
             Some(v) => return v,
-            None => panic!("unknown intrinsic '{}'", key)
+            None => bug!("unknown intrinsic '{}'", key)
         }
     }
 
@@ -785,7 +785,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         match &self.sess().target.target.target_pointer_width[..] {
             "32" => 1 << 31,
             "64" => 1 << 47,
-            _ => unreachable!() // error handled by config::build_target_config
+            _ => bug!() // error handled by config::build_target_config
         }
     }
 
diff --git a/src/librustc_trans/controlflow.rs b/src/librustc_trans/controlflow.rs
index 04562087af7..6d4b02f076c 100644
--- a/src/librustc_trans/controlflow.rs
+++ b/src/librustc_trans/controlflow.rs
@@ -322,7 +322,7 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def())  {
                 Some(Def::Label(loop_id)) => loop_id,
                 r => {
-                    bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r))
+                    bug!("{:?} in def-map for label", r)
                 }
             }
         }
diff --git a/src/librustc_trans/datum.rs b/src/librustc_trans/datum.rs
index 6f96b5769bf..0ed38f06817 100644
--- a/src/librustc_trans/datum.rs
+++ b/src/librustc_trans/datum.rs
@@ -584,10 +584,10 @@ impl<'tcx> Datum<'tcx, Expr> {
 
     /// Asserts that this datum *is* an lvalue and returns it.
     #[allow(dead_code)] // potentially useful
-    pub fn assert_lvalue(self, bcx: Block) -> Datum<'tcx, Lvalue> {
+    pub fn assert_lvalue(self) -> Datum<'tcx, Lvalue> {
         self.match_kind(
             |d| d,
-            |_| bcx.sess().bug("assert_lvalue given rvalue"))
+            |_| bug!("assert_lvalue given rvalue"))
     }
 
     pub fn store_to_dest<'blk>(self,
diff --git a/src/librustc_trans/debuginfo/create_scope_map.rs b/src/librustc_trans/debuginfo/create_scope_map.rs
index 20e8a3fb0cf..a7f2bf4a5fa 100644
--- a/src/librustc_trans/debuginfo/create_scope_map.rs
+++ b/src/librustc_trans/debuginfo/create_scope_map.rs
@@ -98,7 +98,7 @@ fn with_new_scope<F>(cx: &CrateContext,
     }
 
     if scope_stack.last().unwrap().scope_metadata != scope_metadata {
-        cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
+        span_bug!(scope_span, "debuginfo: Inconsistency in scope management.");
     }
 
     scope_stack.pop();
diff --git a/src/librustc_trans/debuginfo/gdb.rs b/src/librustc_trans/debuginfo/gdb.rs
index 5612f3d1e90..cf312855d75 100644
--- a/src/librustc_trans/debuginfo/gdb.rs
+++ b/src/librustc_trans/debuginfo/gdb.rs
@@ -71,7 +71,7 @@ pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
 
             let section_var = declare::define_global(ccx, section_var_name,
                                                      llvm_type).unwrap_or_else(||{
-                ccx.sess().bug(&format!("symbol `{}` is already defined", section_var_name))
+                bug!("symbol `{}` is already defined", section_var_name)
             });
             llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
             llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs
index af7ccdb6cf5..5690b18bc8e 100644
--- a/src/librustc_trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/debuginfo/metadata.rs
@@ -102,25 +102,22 @@ impl<'tcx> TypeMap<'tcx> {
     // Adds a Ty to metadata mapping to the TypeMap. The method will fail if
     // the mapping already exists.
     fn register_type_with_metadata<'a>(&mut self,
-                                       cx: &CrateContext<'a, 'tcx>,
                                        type_: Ty<'tcx>,
                                        metadata: DIType) {
         if self.type_to_metadata.insert(type_, metadata).is_some() {
-            cx.sess().bug(&format!("Type metadata for Ty '{}' is already in the TypeMap!",
-                                   type_));
+            bug!("Type metadata for Ty '{}' is already in the TypeMap!", type_);
         }
     }
 
     // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
     // fail if the mapping already exists.
     fn register_unique_id_with_metadata(&mut self,
-                                        cx: &CrateContext,
                                         unique_type_id: UniqueTypeId,
                                         metadata: DIType) {
         if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
             let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id);
-            cx.sess().bug(&format!("Type metadata for unique id '{}' is already in the TypeMap!",
-                                  &unique_type_id_str[..]));
+            bug!("Type metadata for unique id '{}' is already in the TypeMap!",
+                 &unique_type_id_str[..]);
         }
     }
 
@@ -305,8 +302,8 @@ impl<'tcx> TypeMap<'tcx> {
                 }
             },
             _ => {
-                cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {:?}",
-                                       type_))
+                bug!("get_unique_type_id_of_type() - unexpected type: {:?}",
+                     type_)
             }
         };
 
@@ -415,8 +412,8 @@ fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
 
     // Insert the stub into the TypeMap in order to allow for recursive references
     let mut type_map = debug_context(cx).type_map.borrow_mut();
-    type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata_stub);
-    type_map.register_type_with_metadata(cx, unfinished_type, metadata_stub);
+    type_map.register_unique_id_with_metadata(unique_type_id, metadata_stub);
+    type_map.register_type_with_metadata(unfinished_type, metadata_stub);
 
     UnfinishedMetadata {
         unfinished_type: unfinished_type,
@@ -452,10 +449,9 @@ impl<'tcx> RecursiveTypeDescription<'tcx> {
                     let type_map = debug_context(cx).type_map.borrow();
                     if type_map.find_metadata_for_unique_id(unique_type_id).is_none() ||
                        type_map.find_metadata_for_type(unfinished_type).is_none() {
-                        cx.sess().bug(&format!("Forward declaration of potentially recursive type \
-                                              '{:?}' was not found in TypeMap!",
-                                              unfinished_type)
-                                      );
+                        bug!("Forward declaration of potentially recursive type \
+                              '{:?}' was not found in TypeMap!",
+                             unfinished_type);
                     }
                 }
 
@@ -640,9 +636,9 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let def_id = match trait_type.sty {
         ty::TyTrait(ref data) => data.principal_def_id(),
         _ => {
-            cx.sess().bug(&format!("debuginfo: Unexpected trait-object type in \
-                                   trait_pointer_metadata(): {:?}",
-                                   trait_type));
+            bug!("debuginfo: Unexpected trait-object type in \
+                  trait_pointer_metadata(): {:?}",
+                 trait_type);
         }
     };
 
@@ -688,7 +684,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         // There is already an equivalent type in the TypeMap.
                         // Register this Ty as an alias in the cache and
                         // return the cached metadata.
-                        type_map.register_type_with_metadata(cx, t, metadata);
+                        type_map.register_type_with_metadata(t, metadata);
                         return metadata;
                     },
                     None => {
@@ -803,8 +799,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                    usage_site_span).finalize(cx)
         }
         _ => {
-            cx.sess().bug(&format!("debuginfo: unexpected type in type_metadata: {:?}",
-                                  sty))
+            bug!("debuginfo: unexpected type in type_metadata: {:?}", sty)
         }
     };
 
@@ -818,13 +813,13 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 None => {
                     let unique_type_id_str =
                         type_map.get_unique_type_id_as_string(unique_type_id);
-                    let error_message = format!("Expected type metadata for unique \
-                                                 type id '{}' to already be in \
-                                                 the debuginfo::TypeMap but it \
-                                                 was not. (Ty = {})",
-                                                &unique_type_id_str[..],
-                                                t);
-                    cx.sess().span_bug(usage_site_span, &error_message[..]);
+                    span_bug!(usage_site_span,
+                              "Expected type metadata for unique \
+                               type id '{}' to already be in \
+                               the debuginfo::TypeMap but it \
+                               was not. (Ty = {})",
+                              &unique_type_id_str[..],
+                              t);
                 }
             };
 
@@ -833,22 +828,22 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     if metadata != metadata_for_uid {
                         let unique_type_id_str =
                             type_map.get_unique_type_id_as_string(unique_type_id);
-                        let error_message = format!("Mismatch between Ty and \
-                                                     UniqueTypeId maps in \
-                                                     debuginfo::TypeMap. \
-                                                     UniqueTypeId={}, Ty={}",
-                            &unique_type_id_str[..],
-                            t);
-                        cx.sess().span_bug(usage_site_span, &error_message[..]);
+                        span_bug!(usage_site_span,
+                                  "Mismatch between Ty and \
+                                   UniqueTypeId maps in \
+                                   debuginfo::TypeMap. \
+                                   UniqueTypeId={}, Ty={}",
+                                  &unique_type_id_str[..],
+                                  t);
                     }
                 }
                 None => {
-                    type_map.register_type_with_metadata(cx, t, metadata);
+                    type_map.register_type_with_metadata(t, metadata);
                 }
             }
         } else {
-            type_map.register_type_with_metadata(cx, t, metadata);
-            type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata);
+            type_map.register_type_with_metadata(t, metadata);
+            type_map.register_unique_id_with_metadata(unique_type_id, metadata);
         }
     }
 
@@ -901,16 +896,16 @@ pub fn scope_metadata(fcx: &FunctionContext,
                   error_reporting_span: Span)
                -> DIScope {
     let scope_map = &fcx.debug_context
-                        .get_ref(fcx.ccx, error_reporting_span)
+                        .get_ref(error_reporting_span)
                         .scope_map;
     match scope_map.borrow().get(&node_id).cloned() {
         Some(scope_metadata) => scope_metadata,
         None => {
             let node = fcx.ccx.tcx().map.get(node_id);
 
-            fcx.ccx.sess().span_bug(error_reporting_span,
-                &format!("debuginfo: Could not find scope info for node {:?}",
-                        node));
+            span_bug!(error_reporting_span,
+                      "debuginfo: Could not find scope info for node {:?}",
+                      node);
         }
     }
 }
@@ -945,7 +940,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyFloat(float_ty) => {
             (float_ty.ty_to_string(), DW_ATE_float)
         },
-        _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
+        _ => bug!("debuginfo::basic_type_metadata - t is invalid type")
     };
 
     let llvm_type = type_of::type_of(cx, t);
@@ -1162,7 +1157,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
     let (variant, substs) = match struct_type.sty {
         ty::TyStruct(def, substs) => (def.struct_variant(), substs),
-        _ => cx.tcx().sess.bug("prepare_struct_metadata on a non-struct")
+        _ => bug!("prepare_struct_metadata on a non-struct")
     };
 
     let (containing_scope, _) = get_namespace_and_span_for_item(cx, variant.did);
@@ -1362,7 +1357,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                         ty::VariantKind::Struct => {
                             non_null_variant.fields[0].name.to_string()
                         }
-                        ty::VariantKind::Unit => unreachable!()
+                        ty::VariantKind::Unit => bug!()
                     },
                     llvm_type: non_null_llvm_type,
                     type_metadata: non_null_type_metadata,
@@ -1452,7 +1447,7 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
                     }
                 ]
             },
-            adt::CEnum(..) => cx.sess().span_bug(self.span, "This should be unreachable.")
+            adt::CEnum(..) => span_bug!(self.span, "This should be unreachable.")
         }
     }
 }
@@ -1747,8 +1742,8 @@ fn set_members_of_composite_type(cx: &CrateContext,
         let mut composite_types_completed =
             debug_context(cx).composite_types_completed.borrow_mut();
         if composite_types_completed.contains(&composite_type_metadata) {
-            cx.sess().bug("debuginfo::set_members_of_composite_type() - \
-                           Already completed forward declaration re-encountered.");
+            bug!("debuginfo::set_members_of_composite_type() - \
+                  Already completed forward declaration re-encountered.");
         } else {
             composite_types_completed.insert(composite_type_metadata);
         }
@@ -1855,20 +1850,19 @@ pub fn create_global_var_metadata(cx: &CrateContext,
                 hir::ItemStatic(..) => (item.name, item.span),
                 hir::ItemConst(..) => (item.name, item.span),
                 _ => {
-                    cx.sess()
-                      .span_bug(item.span,
-                                &format!("debuginfo::\
-                                         create_global_var_metadata() -
-                                         Captured var-id refers to \
-                                         unexpected ast_item variant: {:?}",
-                                        var_item))
+                    span_bug!(item.span,
+                              "debuginfo::\
+                               create_global_var_metadata() -
+                               Captured var-id refers to \
+                               unexpected ast_item variant: {:?}",
+                              var_item)
                 }
             }
         },
-        _ => cx.sess().bug(&format!("debuginfo::create_global_var_metadata() \
-                                    - Captured var-id refers to unexpected \
-                                    hir_map variant: {:?}",
-                                   var_item))
+        _ => bug!("debuginfo::create_global_var_metadata() \
+                   - Captured var-id refers to unexpected \
+                   hir_map variant: {:?}",
+                  var_item)
     };
 
     let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
@@ -1924,15 +1918,15 @@ pub fn create_local_var_metadata(bcx: Block, local: &hir::Local) {
         let datum = match locals.get(&node_id) {
             Some(datum) => datum,
             None => {
-                bcx.sess().span_bug(span,
-                    &format!("no entry in lllocals table for {}",
-                            node_id));
+                span_bug!(span,
+                          "no entry in lllocals table for {}",
+                          node_id);
             }
         };
 
         if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
-            cx.sess().span_bug(span, "debuginfo::create_local_var_metadata() - \
-                                      Referenced variable location is not an alloca!");
+            span_bug!(span, "debuginfo::create_local_var_metadata() - \
+                             Referenced variable location is not an alloca!");
         }
 
         let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
@@ -1968,7 +1962,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let variable_name = match ast_item {
         None => {
-            cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
+            span_bug!(span, "debuginfo::create_captured_var_metadata: node not found");
         }
         Some(hir_map::NodeLocal(pat)) => {
             match pat.node {
@@ -1976,28 +1970,25 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     path1.node.name
                 }
                 _ => {
-                    cx.sess()
-                      .span_bug(span,
-                                &format!(
-                                "debuginfo::create_captured_var_metadata() - \
-                                 Captured var-id refers to unexpected \
-                                 hir_map variant: {:?}",
-                                 ast_item));
+                    span_bug!(span,
+                              "debuginfo::create_captured_var_metadata() - \
+                               Captured var-id refers to unexpected \
+                               hir_map variant: {:?}",
+                              ast_item);
                 }
             }
         }
         _ => {
-            cx.sess()
-              .span_bug(span,
-                        &format!("debuginfo::create_captured_var_metadata() - \
-                                 Captured var-id refers to unexpected \
-                                 hir_map variant: {:?}",
-                                ast_item));
+            span_bug!(span,
+                      "debuginfo::create_captured_var_metadata() - \
+                       Captured var-id refers to unexpected \
+                       hir_map variant: {:?}",
+                      ast_item);
         }
     };
 
     let variable_type = common::node_id_type(bcx, node_id);
-    let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
+    let scope_metadata = bcx.fcx.debug_context.get_ref(span).fn_metadata;
 
     // env_pointer is the alloca containing the pointer to the environment,
     // so it's type is **EnvironmentType. In order to find out the type of
@@ -2096,7 +2087,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
     let scope_metadata = bcx
                          .fcx
                          .debug_context
-                         .get_ref(bcx.ccx(), arg.pat.span)
+                         .get_ref(arg.pat.span)
                          .fn_metadata;
     let locals = bcx.fcx.lllocals.borrow();
 
@@ -2104,22 +2095,20 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
         let datum = match locals.get(&node_id) {
             Some(v) => v,
             None => {
-                bcx.sess().span_bug(span,
-                    &format!("no entry in lllocals table for {}",
-                            node_id));
+                span_bug!(span, "no entry in lllocals table for {}", node_id);
             }
         };
 
         if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
-            bcx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
-                                       Referenced variable location is not an alloca!");
+            span_bug!(span, "debuginfo::create_argument_metadata() - \
+                             Referenced variable location is not an alloca!");
         }
 
         let argument_index = {
             let counter = &bcx
                           .fcx
                           .debug_context
-                          .get_ref(bcx.ccx(), span)
+                          .get_ref(span)
                           .argument_counter;
             let argument_index = counter.get();
             counter.set(argument_index + 1);
diff --git a/src/librustc_trans/debuginfo/mod.rs b/src/librustc_trans/debuginfo/mod.rs
index 66e33698389..6b92989cf46 100644
--- a/src/librustc_trans/debuginfo/mod.rs
+++ b/src/librustc_trans/debuginfo/mod.rs
@@ -119,18 +119,19 @@ pub enum FunctionDebugContext {
 
 impl FunctionDebugContext {
     fn get_ref<'a>(&'a self,
-                   cx: &CrateContext,
                    span: Span)
                    -> &'a FunctionDebugContextData {
         match *self {
             FunctionDebugContext::RegularContext(box ref data) => data,
             FunctionDebugContext::DebugInfoDisabled => {
-                cx.sess().span_bug(span,
-                                   FunctionDebugContext::debuginfo_disabled_message());
+                span_bug!(span,
+                          "{}",
+                          FunctionDebugContext::debuginfo_disabled_message());
             }
             FunctionDebugContext::FunctionWithoutDebugInfo => {
-                cx.sess().span_bug(span,
-                                   FunctionDebugContext::should_be_ignored_message());
+                span_bug!(span,
+                          "{}",
+                          FunctionDebugContext::should_be_ignored_message());
             }
         }
     }
@@ -253,7 +254,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     (item.name, fn_decl, generics, top_level_block, item.span, true)
                 }
                 _ => {
-                    cx.sess().span_bug(item.span,
+                    span_bug!(item.span,
                         "create_function_debug_context: item bound to non-function");
                 }
             }
@@ -273,9 +274,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                      true)
                 }
                 _ => {
-                    cx.sess().span_bug(impl_item.span,
-                                       "create_function_debug_context() \
-                                        called on non-method impl item?!")
+                    span_bug!(impl_item.span,
+                              "create_function_debug_context() \
+                               called on non-method impl item?!")
                 }
             }
         }
@@ -293,7 +294,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         // Don't try to lookup the item path:
                         false)
                 }
-                _ => cx.sess().span_bug(expr.span,
+                _ => span_bug!(expr.span,
                         "create_function_debug_context: expected an expr_fn_block here")
             }
         }
@@ -312,10 +313,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                      true)
                 }
                 _ => {
-                    cx.sess()
-                      .bug(&format!("create_function_debug_context: \
-                                    unexpected sort of node: {:?}",
-                                    fnitem))
+                    bug!("create_function_debug_context: \
+                          unexpected sort of node: {:?}",
+                         fnitem)
                 }
             }
         }
@@ -324,9 +324,9 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         hir_map::NodeStructCtor(..) => {
             return FunctionDebugContext::FunctionWithoutDebugInfo;
         }
-        _ => cx.sess().bug(&format!("create_function_debug_context: \
-                                    unexpected sort of node: {:?}",
-                                   fnitem))
+        _ => bug!("create_function_debug_context: \
+                   unexpected sort of node: {:?}",
+                  fnitem)
     };
 
     // This can be the case for functions inlined from another crate
@@ -441,7 +441,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 (sig, closure_type.abi)
             }
 
-            _ => cx.sess().bug("get_function_metdata: Expected a function type!")
+            _ => bug!("get_function_metdata: Expected a function type!")
         };
 
         let mut signature = Vec::with_capacity(sig.inputs.len() + 1);
@@ -640,7 +640,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ArgumentVariable(_) | CapturedVariable => {
             assert!(!bcx.fcx
                         .debug_context
-                        .get_ref(cx, span)
+                        .get_ref(span)
                         .source_locations_enabled
                         .get());
             source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
diff --git a/src/librustc_trans/debuginfo/namespace.rs b/src/librustc_trans/debuginfo/namespace.rs
index 552188ae2a6..445f85c52fc 100644
--- a/src/librustc_trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/debuginfo/namespace.rs
@@ -126,9 +126,9 @@ pub fn namespace_for_item(cx: &CrateContext, def_id: DefId) -> Rc<NamespaceTreeN
         match parent_node {
             Some(node) => node,
             None => {
-                cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
-                                       path too short for {:?}",
-                                      def_id));
+                bug!("debuginfo::namespace_for_item(): \
+                      path too short for {:?}",
+                     def_id);
             }
         }
     })
diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs
index 71dd3e432df..a6aa8df92db 100644
--- a/src/librustc_trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/debuginfo/type_names.rs
@@ -154,8 +154,8 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::TyInfer(_) |
         ty::TyProjection(..) |
         ty::TyParam(_) => {
-            cx.sess().bug(&format!("debuginfo: Trying to create type name for \
-                unexpected type: {:?}", t));
+            bug!("debuginfo: Trying to create type name for \
+                unexpected type: {:?}", t);
         }
     }
 
@@ -178,7 +178,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 }
 
                 if path_element_count == 0 {
-                    cx.sess().bug("debuginfo: Encountered empty item path!");
+                    bug!("debuginfo: Encountered empty item path!");
                 }
 
                 output.pop();
diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs
index d2ae74569e7..61dc3dc3f8f 100644
--- a/src/librustc_trans/debuginfo/utils.rs
+++ b/src/librustc_trans/debuginfo/utils.rs
@@ -91,8 +91,8 @@ pub fn assert_type_for_node_id(cx: &CrateContext,
                            node_id: ast::NodeId,
                            error_reporting_span: Span) {
     if !cx.tcx().node_types().contains_key(&node_id) {
-        cx.sess().span_bug(error_reporting_span,
-                           "debuginfo: Could not find type for node id!");
+        span_bug!(error_reporting_span,
+                  "debuginfo: Could not find type for node id!");
     }
 }
 
diff --git a/src/librustc_trans/declare.rs b/src/librustc_trans/declare.rs
index 28a70fd5e0b..f49d303a5a8 100644
--- a/src/librustc_trans/declare.rs
+++ b/src/librustc_trans/declare.rs
@@ -38,7 +38,7 @@ use libc::c_uint;
 pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRef {
     debug!("declare_global(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
-        ccx.sess().bug(&format!("name {:?} contains an interior null byte", name))
+        bug!("name {:?} contains an interior null byte", name)
     });
     unsafe {
         llvm::LLVMGetOrInsertGlobal(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
@@ -53,7 +53,7 @@ pub fn declare_global(ccx: &CrateContext, name: &str, ty: Type) -> llvm::ValueRe
 fn declare_raw_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty: Type) -> ValueRef {
     debug!("declare_raw_fn(name={:?}, ty={:?})", name, ty);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
-        ccx.sess().bug(&format!("name {:?} contains an interior null byte", name))
+        bug!("name {:?} contains an interior null byte", name)
     });
     let llfn = unsafe {
         llvm::LLVMGetOrInsertFunction(ccx.llmod(), namebuf.as_ptr(), ty.to_ref())
@@ -152,7 +152,7 @@ pub fn define_internal_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 pub fn get_defined_value(ccx: &CrateContext, name: &str) -> Option<ValueRef> {
     debug!("get_defined_value(name={:?})", name);
     let namebuf = CString::new(name).unwrap_or_else(|_|{
-        ccx.sess().bug(&format!("name {:?} contains an interior null byte", name))
+        bug!("name {:?} contains an interior null byte", name)
     });
     let val = unsafe { llvm::LLVMGetNamedValue(ccx.llmod(), namebuf.as_ptr()) };
     if val.is_null() {
diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs
index b2e2e93a2be..5e193b96278 100644
--- a/src/librustc_trans/expr.rs
+++ b/src/librustc_trans/expr.rs
@@ -388,7 +388,7 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         .reify(bcx.ccx()).to_expr_datum();
                 }
                 _ => {
-                    unreachable!("{} cannot be reified to a fn ptr", datum.ty)
+                    bug!("{} cannot be reified to a fn ptr", datum.ty)
                 }
             }
         }
@@ -516,16 +516,16 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let repr_source = adt::represent_type(bcx.ccx(), source.ty);
             let src_fields = match &*repr_source {
                 &adt::Repr::Univariant(ref s, _) => &s.fields,
-                _ => bcx.sess().span_bug(span,
-                                         &format!("Non univariant struct? (repr_source: {:?})",
-                                                  repr_source)),
+                _ => span_bug!(span,
+                               "Non univariant struct? (repr_source: {:?})",
+                               repr_source),
             };
             let repr_target = adt::represent_type(bcx.ccx(), target.ty);
             let target_fields = match &*repr_target {
                 &adt::Repr::Univariant(ref s, _) => &s.fields,
-                _ => bcx.sess().span_bug(span,
-                                         &format!("Non univariant struct? (repr_target: {:?})",
-                                                  repr_target)),
+                _ => span_bug!(span,
+                               "Non univariant struct? (repr_target: {:?})",
+                               repr_target),
             };
 
             let coerce_index = match kind {
@@ -555,9 +555,9 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             }
         }
-        _ => bcx.sess().bug(&format!("coerce_unsized: invalid coercion {:?} -> {:?}",
-                                     source.ty,
-                                     target.ty))
+        _ => bug!("coerce_unsized: invalid coercion {:?} -> {:?}",
+                  source.ty,
+                  target.ty)
     }
     bcx
 }
@@ -671,8 +671,8 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 ty::TyBox(..) => {
                     trans_uniq_expr(bcx, expr, box_ty, &contents, contents_ty)
                 }
-                _ => bcx.sess().span_bug(expr.span,
-                                         "expected unique box")
+                _ => span_bug!(expr.span,
+                               "expected unique box")
             }
 
         }
@@ -708,11 +708,11 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             trans_imm_cast(bcx, &val, expr.id)
         }
         _ => {
-            bcx.tcx().sess.span_bug(
+            span_bug!(
                 expr.span,
-                &format!("trans_rvalue_datum_unadjusted reached \
-                         fall-through case: {:?}",
-                        expr.node));
+                "trans_rvalue_datum_unadjusted reached \
+                 fall-through case: {:?}",
+                expr.node);
         }
     }
 }
@@ -798,9 +798,9 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 bcx.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap().unwrap();
             let elt_ty = match ref_ty.builtin_deref(true, ty::NoPreference) {
                 None => {
-                    bcx.tcx().sess.span_bug(index_expr.span,
-                                            "index method didn't return a \
-                                             dereferenceable type?!")
+                    span_bug!(index_expr.span,
+                              "index method didn't return a \
+                              dereferenceable type?!")
                 }
                 Some(elt_tm) => elt_tm.ty,
             };
@@ -895,9 +895,7 @@ pub fn trans_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, def: Def)
             match bcx.fcx.llupvars.borrow().get(&nid) {
                 Some(&val) => Datum::new(val, local_ty, lval),
                 None => {
-                    bcx.sess().bug(&format!(
-                        "trans_var: no llval for upvar {} found",
-                        nid));
+                    bug!("trans_var: no llval for upvar {} found", nid);
                 }
             }
         }
@@ -905,16 +903,14 @@ pub fn trans_var<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, def: Def)
             let datum = match bcx.fcx.lllocals.borrow().get(&nid) {
                 Some(&v) => v,
                 None => {
-                    bcx.sess().bug(&format!(
-                        "trans_var: no datum for local/arg {} found",
-                        nid));
+                    bug!("trans_var: no datum for local/arg {} found", nid);
                 }
             };
             debug!("take_local(nid={}, v={:?}, ty={})",
                    nid, Value(datum.val), datum.ty);
             datum
         }
-        _ => unreachable!("{:?} should not reach expr::trans_var", def)
+        _ => bug!("{:?} should not reach expr::trans_var", def)
     }
 }
 
@@ -1051,11 +1047,11 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             bcx
         }
         _ => {
-            bcx.tcx().sess.span_bug(
+            span_bug!(
                 expr.span,
-                &format!("trans_rvalue_stmt_unadjusted reached \
-                         fall-through case: {:?}",
-                        expr.node));
+                "trans_rvalue_stmt_unadjusted reached \
+                 fall-through case: {:?}",
+                expr.node);
         }
     }
 }
@@ -1114,11 +1110,9 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     tvec::trans_lit_str(bcx, expr, (*s).clone(), dest)
                 }
                 _ => {
-                    bcx.tcx()
-                       .sess
-                       .span_bug(expr.span,
-                                 "trans_rvalue_dps_unadjusted shouldn't be \
-                                  translating this type of literal")
+                    span_bug!(expr.span,
+                              "trans_rvalue_dps_unadjusted shouldn't be \
+                              translating this type of literal")
                 }
             }
         }
@@ -1141,9 +1135,9 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let (def_id, substs) = match expr_ty(bcx, expr).sty {
                 ty::TyClosure(def_id, ref substs) => (def_id, substs),
                 ref t =>
-                    bcx.tcx().sess.span_bug(
+                    span_bug!(
                         expr.span,
-                        &format!("closure expr without closure type: {:?}", t)),
+                        "closure expr without closure type: {:?}", t),
             };
 
             closure::trans_closure_expr(dest,
@@ -1172,8 +1166,8 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                         Callee::ptr(f)
                     }
                     _ => {
-                        bcx.tcx().sess.span_bug(expr.span,
-                            &format!("type of callee is not a fn: {}", f.ty));
+                        span_bug!(expr.span,
+                            "type of callee is not a fn: {}", f.ty);
                     }
                 }, ArgExprs(&args))
             };
@@ -1205,20 +1199,20 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         hir::ExprCast(..) => {
             // Trait casts used to come this way, now they should be coercions.
-            bcx.tcx().sess.span_bug(expr.span, "DPS expr_cast (residual trait cast?)")
+            span_bug!(expr.span, "DPS expr_cast (residual trait cast?)")
         }
         hir::ExprAssignOp(op, _, _) => {
-            bcx.tcx().sess.span_bug(
+            span_bug!(
                 expr.span,
-                &format!("augmented assignment `{}=` should always be a rvalue_stmt",
-                         rustc_front::util::binop_to_string(op.node)))
+                "augmented assignment `{}=` should always be a rvalue_stmt",
+                rustc_front::util::binop_to_string(op.node))
         }
         _ => {
-            bcx.tcx().sess.span_bug(
+            span_bug!(
                 expr.span,
-                &format!("trans_rvalue_dps_unadjusted reached fall-through \
-                         case: {:?}",
-                        expr.node));
+                "trans_rvalue_dps_unadjusted reached fall-through \
+                 case: {:?}",
+                expr.node);
         }
     }
 }
@@ -1261,9 +1255,9 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             bcx
         }
         _ => {
-            bcx.tcx().sess.span_bug(ref_expr.span, &format!(
-                "Non-DPS def {:?} referened by {}",
-                def, bcx.node_id_to_string(ref_expr.id)));
+            span_bug!(ref_expr.span,
+                      "Non-DPS def {:?} referened by {}",
+                      def, bcx.node_id_to_string(ref_expr.id));
         }
     }
 }
@@ -1301,7 +1295,7 @@ fn trans_struct<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         None => {
             if need_base.iter().any(|b| *b) {
-                tcx.sess.span_bug(expr_span, "missing fields and no base expr")
+                span_bug!(expr_span, "missing fields and no base expr")
             }
             None
         }
@@ -1415,7 +1409,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 bcx = trans_into(bcx, &base.expr, SaveIn(addr.value));
             },
             ExprKind::RvalueStmt => {
-                bcx.tcx().sess.bug("unexpected expr kind for struct base expr")
+                bug!("unexpected expr kind for struct base expr")
             }
             _ => {
                 let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &base.expr, "base"));
@@ -1728,7 +1722,7 @@ fn trans_scalar_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
           base::compare_scalar_types(bcx, lhs, rhs, lhs_t, op.node, binop_debug_loc)
       }
       _ => {
-        bcx.tcx().sess.span_bug(binop_expr.span, "unexpected binop");
+        span_bug!(binop_expr.span, "unexpected binop");
       }
     };
 
@@ -1968,12 +1962,11 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         (Float, Int(I)) => FPToSI(bcx, llexpr, ll_t_out),
         (Float, Int(_)) => FPToUI(bcx, llexpr, ll_t_out),
 
-        _ => ccx.sess().span_bug(expr.span,
-                                  &format!("translating unsupported cast: \
-                                            {:?} -> {:?}",
-                                           t_in,
-                                           t_out)
-                                 )
+        _ => span_bug!(expr.span,
+                       "translating unsupported cast: \
+                        {:?} -> {:?}",
+                       t_in,
+                       t_out)
     };
     return immediate_rvalue_bcx(bcx, newval, t_out).to_expr_datumblock();
 }
@@ -2140,10 +2133,10 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
 
         _ => {
-            bcx.tcx().sess.span_bug(
+            span_bug!(
                 expr.span,
-                &format!("deref invoked on expr of invalid type {:?}",
-                        datum.ty));
+                "deref invoked on expr of invalid type {:?}",
+                datum.ty);
         }
     };
 
@@ -2200,16 +2193,16 @@ impl OverflowOpViaIntrinsic {
             TyInt(Is) => match &tcx.sess.target.target.target_pointer_width[..] {
                 "32" => TyInt(I32),
                 "64" => TyInt(I64),
-                _ => panic!("unsupported target word size")
+                _ => bug!("unsupported target word size")
             },
             TyUint(Us) => match &tcx.sess.target.target.target_pointer_width[..] {
                 "32" => TyUint(U32),
                 "64" => TyUint(U64),
-                _ => panic!("unsupported target word size")
+                _ => bug!("unsupported target word size")
             },
             ref t @ TyUint(_) | ref t @ TyInt(_) => t.clone(),
-            _ => panic!("tried to get overflow intrinsic for {:?} applied to non-int type",
-                        *self)
+            _ => bug!("tried to get overflow intrinsic for {:?} applied to non-int type",
+                      *self)
         };
 
         match *self {
@@ -2224,7 +2217,7 @@ impl OverflowOpViaIntrinsic {
                 TyUint(U32) => "llvm.uadd.with.overflow.i32",
                 TyUint(U64) => "llvm.uadd.with.overflow.i64",
 
-                _ => unreachable!(),
+                _ => bug!(),
             },
             OverflowOpViaIntrinsic::Sub => match new_sty {
                 TyInt(I8) => "llvm.ssub.with.overflow.i8",
@@ -2237,7 +2230,7 @@ impl OverflowOpViaIntrinsic {
                 TyUint(U32) => "llvm.usub.with.overflow.i32",
                 TyUint(U64) => "llvm.usub.with.overflow.i64",
 
-                _ => unreachable!(),
+                _ => bug!(),
             },
             OverflowOpViaIntrinsic::Mul => match new_sty {
                 TyInt(I8) => "llvm.smul.with.overflow.i8",
@@ -2250,7 +2243,7 @@ impl OverflowOpViaIntrinsic {
                 TyUint(U32) => "llvm.umul.with.overflow.i32",
                 TyUint(U64) => "llvm.umul.with.overflow.i64",
 
-                _ => unreachable!(),
+                _ => bug!(),
             },
         }
     }
@@ -2337,7 +2330,7 @@ fn build_nonzero_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let int_value = BitCast(bcx, value, Type::ix(bcx.ccx(), width));
             build_nonzero_check(bcx, int_value, binop_debug_loc)
         },
-        _ => panic!("build_nonzero_check: expected Integer or Vector, found {:?}", kind),
+        _ => bug!("build_nonzero_check: expected Integer or Vector, found {:?}", kind),
     }
 }
 
@@ -2423,11 +2416,11 @@ fn expr_kind(tcx: &TyCtxt, expr: &hir::Expr) -> ExprKind {
                 Def::AssociatedConst(..) => ExprKind::RvalueDatum,
 
                 def => {
-                    tcx.sess.span_bug(
+                    span_bug!(
                         expr.span,
-                        &format!("uncategorized def for expr {}: {:?}",
-                                expr.id,
-                                def));
+                        "uncategorized def for expr {}: {:?}",
+                        expr.id,
+                        def);
                 }
             }
         }
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index 1af816845b0..6ef4ed4b87e 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -367,7 +367,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     });
     let vtbl = match fulfill_obligation(bcx.ccx(), DUMMY_SP, trait_ref) {
         traits::VtableImpl(data) => data,
-        _ => tcx.sess.bug(&format!("dtor for {:?} is not an impl???", t))
+        _ => bug!("dtor for {:?} is not an impl???", t)
     };
     let dtor_did = def.destructor().unwrap();
     bcx = Callee::def(bcx.ccx(), dtor_did, vtbl.substs)
@@ -482,7 +482,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
             (bcx.mul(info, C_uint(bcx.ccx(), unit_size)),
              C_uint(bcx.ccx(), unit_align))
         }
-        _ => bcx.sess().bug(&format!("Unexpected unsized type, found {}", t))
+        _ => bug!("Unexpected unsized type, found {}", t)
     }
 }
 
diff --git a/src/librustc_trans/inline.rs b/src/librustc_trans/inline.rs
index cf1542b7b03..4d18e3bd495 100644
--- a/src/librustc_trans/inline.rs
+++ b/src/librustc_trans/inline.rs
@@ -102,16 +102,16 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: DefId) -> Option<DefId> {
                 }
                 hir::ItemStruct(ref struct_def, _) => {
                     if struct_def.is_struct() {
-                        ccx.sess().bug("instantiate_inline: called on a \
-                                                                 non-tuple struct")
+                        bug!("instantiate_inline: called on a \
+                              non-tuple struct")
                     } else {
                         ccx.external().borrow_mut().insert(fn_id, Some(struct_def.id()));
                         ccx.external_srcs().borrow_mut().insert(struct_def.id(), fn_id);
                         my_id = struct_def.id();
                     }
                 }
-                _ => ccx.sess().bug("instantiate_inline: item has a \
-                                 non-enum, non-struct parent")
+                _ => bug!("instantiate_inline: item has a \
+                           non-enum, non-struct parent")
             }
             my_id
         }
diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs
index 130a864f5e6..219f970835a 100644
--- a/src/librustc_trans/intrinsic.rs
+++ b/src/librustc_trans/intrinsic.rs
@@ -188,7 +188,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             let sig = tcx.erase_late_bound_regions(&fty.sig);
             (def_id, substs, infer::normalize_associated_type(tcx, &sig))
         }
-        _ => unreachable!("expected fn item type, found {}", callee_ty)
+        _ => bug!("expected fn item type, found {}", callee_ty)
     };
     let arg_tys = sig.inputs;
     let ret_ty = sig.output;
@@ -311,7 +311,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             }
 
             _ => {
-                ccx.sess().bug("expected expr as argument for transmute");
+                bug!("expected expr as argument for transmute");
             }
         }
     }
@@ -323,7 +323,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     if name == "move_val_init" {
         if let callee::ArgExprs(ref exprs) = args {
             let (dest_expr, source_expr) = if exprs.len() != 2 {
-                ccx.sess().bug("expected two exprs as arguments for `move_val_init` intrinsic");
+                bug!("expected two exprs as arguments for `move_val_init` intrinsic");
             } else {
                 (&exprs[0], &exprs[1])
             };
@@ -350,7 +350,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
             return Result::new(bcx, llresult);
         } else {
-            ccx.sess().bug("expected two exprs as arguments for `move_val_init` intrinsic");
+            bug!("expected two exprs as arguments for `move_val_init` intrinsic");
         }
     }
 
@@ -388,7 +388,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
     let ret_ty = match ret_ty {
         ty::FnConverging(ret_ty) => ret_ty,
-        ty::FnDiverging => unreachable!()
+        ty::FnDiverging => bug!()
     };
 
     let llret_ty = type_of::type_of(ccx, ret_ty);
@@ -651,7 +651,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                             } else {
                                 URem(bcx, llargs[0], llargs[1], call_debug_location)
                             },
-                        _ => unreachable!(),
+                        _ => bug!(),
                     },
                 None => {
                     span_invalid_monomorphization_error(
@@ -674,7 +674,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                         "fmul_fast" => FMulFast(bcx, llargs[0], llargs[1], call_debug_location),
                         "fdiv_fast" => FDivFast(bcx, llargs[0], llargs[1], call_debug_location),
                         "frem_fast" => FRemFast(bcx, llargs[0], llargs[1], call_debug_location),
-                        _ => unreachable!(),
+                        _ => bug!(),
                     },
                 None => {
                     span_invalid_monomorphization_error(
@@ -820,7 +820,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         (_, _) => {
             let intr = match Intrinsic::find(&name) {
                 Some(intr) => intr,
-                None => unreachable!("unknown intrinsic '{}'", name),
+                None => bug!("unknown intrinsic '{}'", name),
             };
             fn one<T>(x: Vec<T>) -> T {
                 assert_eq!(x.len(), 1);
@@ -839,7 +839,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                         match x {
                             32 => vec![Type::f32(ccx)],
                             64 => vec![Type::f64(ccx)],
-                            _ => unreachable!()
+                            _ => bug!()
                         }
                     }
                     Pointer(ref t, ref llvm_elem, _const) => {
@@ -1242,7 +1242,7 @@ fn trans_gnu_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             Some(did) => {
                 Callee::def(ccx, did, tcx.mk_substs(Substs::empty())).reify(ccx).val
             }
-            None => ccx.sess().bug("eh_personality_catch not defined"),
+            None => bug!("eh_personality_catch not defined"),
         };
 
         let then = bcx.fcx.new_temp_block("then");
@@ -1357,7 +1357,7 @@ fn generate_filter_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
         Some(did) => {
             Callee::def(ccx, did, tcx.mk_substs(Substs::empty())).reify(ccx).val
         }
-        None => ccx.sess().bug("msvc_try_filter not defined"),
+        None => bug!("msvc_try_filter not defined"),
     };
 
     let output = ty::FnOutput::FnConverging(tcx.types.i32);
@@ -1417,7 +1417,7 @@ fn generate_filter_fn<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
             do_trans(bcx, exn, rbp);
         })
     } else {
-        panic!("unknown target to generate a filter function")
+        bug!("unknown target to generate a filter function")
     }
 }
 
@@ -1513,8 +1513,8 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
     if name.starts_with("simd_shuffle") {
         let n: usize = match name["simd_shuffle".len()..].parse() {
             Ok(n) => n,
-            Err(_) => tcx.sess.span_bug(span,
-                                        "bad `simd_shuffle` instruction only caught in trans?")
+            Err(_) => span_bug!(span,
+                                "bad `simd_shuffle` instruction only caught in trans?")
         };
 
         require_simd!(ret_ty, "return");
@@ -1687,7 +1687,7 @@ fn generic_simd_intrinsic<'blk, 'tcx, 'a>
         simd_or: TyUint, TyInt => Or;
         simd_xor: TyUint, TyInt => Xor;
     }
-    bcx.sess().span_bug(span, "unknown SIMD intrinsic");
+    span_bug!(span, "unknown SIMD intrinsic");
 }
 
 // Returns the width of an int TypeVariant, and if it's signed or not
@@ -1701,7 +1701,7 @@ fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
                 match &ccx.tcx().sess.target.target.target_pointer_width[..] {
                     "32" => 32,
                     "64" => 64,
-                    tws => panic!("Unsupported target word size for isize: {}", tws),
+                    tws => bug!("Unsupported target word size for isize: {}", tws),
                 }
             },
             ast::IntTy::I8 => 8,
@@ -1714,7 +1714,7 @@ fn int_type_width_signed<'tcx>(sty: &ty::TypeVariants<'tcx>, ccx: &CrateContext)
                 match &ccx.tcx().sess.target.target.target_pointer_width[..] {
                     "32" => 32,
                     "64" => 64,
-                    tws => panic!("Unsupported target word size for usize: {}", tws),
+                    tws => bug!("Unsupported target word size for usize: {}", tws),
                 }
             },
             ast::UintTy::U8 => 8,
diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs
index e9687935538..8c6a68cfcf1 100644
--- a/src/librustc_trans/lib.rs
+++ b/src/librustc_trans/lib.rs
@@ -43,7 +43,7 @@ extern crate flate;
 extern crate getopts;
 extern crate graphviz;
 extern crate libc;
-extern crate rustc;
+#[macro_use] extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_data_structures;
 extern crate rustc_front;
diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs
index 65f52fd0799..82b61e15f2b 100644
--- a/src/librustc_trans/meth.rs
+++ b/src/librustc_trans/meth.rs
@@ -186,15 +186,13 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 // this would imply that the Self type being erased is
                 // an object type; this cannot happen because we
                 // cannot cast an unsized type into a trait object
-                tcx.sess.bug(
-                    &format!("cannot get vtable for an object type: {:?}",
-                            data));
+                bug!("cannot get vtable for an object type: {:?}",
+                     data);
             }
             traits::VtableParam(..) => {
-                tcx.sess.bug(
-                    &format!("resolved vtable for {:?} to bad vtable {:?} in trans",
-                            trait_ref,
-                            vtable));
+                bug!("resolved vtable for {:?} to bad vtable {:?} in trans",
+                     trait_ref,
+                     vtable);
             }
         }
     });
@@ -229,8 +227,8 @@ pub fn get_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let trt_id = match tcx.impl_trait_ref(impl_id) {
         Some(t_id) => t_id.def_id,
-        None       => ccx.sess().bug("make_impl_vtable: don't know how to \
-                                      make a vtable for a type impl!")
+        None       => bug!("make_impl_vtable: don't know how to \
+                            make a vtable for a type impl!")
     };
 
     tcx.populate_implementations_for_trait_if_necessary(trt_id);
@@ -256,7 +254,7 @@ pub fn get_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
             let trait_method_type = match tcx.impl_or_trait_item(trait_method_def_id) {
                 ty::MethodTraitItem(m) => m,
-                _ => ccx.sess().bug("should be a method, not other assoc item"),
+                _ => bug!("should be a method, not other assoc item"),
             };
             let name = trait_method_type.name;
 
@@ -330,7 +328,7 @@ pub fn get_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
             }
         }
         None => {
-            tcx.sess.bug(&format!("method {:?} not found in {:?}", name, impl_def_id))
+            bug!("method {:?} not found in {:?}", name, impl_def_id)
         }
     }
 }
diff --git a/src/librustc_trans/mir/block.rs b/src/librustc_trans/mir/block.rs
index a60b03dd724..cbe21664d28 100644
--- a/src/librustc_trans/mir/block.rs
+++ b/src/librustc_trans/mir/block.rs
@@ -166,7 +166,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             ty: callee.ty
                         }, f.abi, &f.sig)
                     }
-                    _ => unreachable!("{} is not callable", callee.ty)
+                    _ => bug!("{} is not callable", callee.ty)
                 };
 
                 // Handle intrinsics old trans wants Expr's for, ourselves.
@@ -295,7 +295,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                         return;
                     }
                     Fn(f) => f,
-                    Virtual(_) => unreachable!("Virtual fn ptr not extracted")
+                    Virtual(_) => bug!("Virtual fn ptr not extracted")
                 };
 
                 // Many different ways to call a function handled here
@@ -417,7 +417,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
             }
             Immediate(llval) => (llval, false),
             Ref(llval) => (llval, true),
-            FatPtr(_, _) => unreachable!("fat pointers handled above")
+            FatPtr(_, _) => bug!("fat pointers handled above")
         };
 
         if by_ref && !arg.is_indirect() {
@@ -470,9 +470,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
         let lv_ty = lv.ty.to_ty(bcx.tcx());
         let result_types = match lv_ty.sty {
             ty::TyTuple(ref tys) => tys,
-            _ => bcx.tcx().sess.span_bug(
+            _ => span_bug!(
                 self.mir.span,
-                &format!("bad final argument to \"rust-call\" fn {:?}", lv_ty))
+                "bad final argument to \"rust-call\" fn {:?}", lv_ty)
         };
 
         let base_repr = adt::represent_type(bcx.ccx(), lv_ty);
diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs
index 2e154c40875..cf85595c08e 100644
--- a/src/librustc_trans/mir/constant.rs
+++ b/src/librustc_trans/mir/constant.rs
@@ -89,10 +89,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
             ConstVal::Struct(_) | ConstVal::Tuple(_) |
             ConstVal::Array(..) | ConstVal::Repeat(..) |
             ConstVal::Function(_) => {
-                unreachable!("MIR must not use {:?} (which refers to a local ID)", cv)
+                bug!("MIR must not use {:?} (which refers to a local ID)", cv)
             }
             ConstVal::Char(c) => C_integral(Type::char(ccx), c as u64, false),
-            ConstVal::Dummy => unreachable!(),
+            ConstVal::Dummy => bug!(),
         }
     }
 
diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs
index f5f8c23a982..c9087181f9d 100644
--- a/src/librustc_trans/mir/lvalue.rs
+++ b/src/librustc_trans/mir/lvalue.rs
@@ -81,7 +81,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 assert!(lvalue.llextra != ptr::null_mut());
                 lvalue.llextra
             }
-            _ => bcx.sess().bug("unexpected type in lvalue_len"),
+            _ => bug!("unexpected type in lvalue_len"),
         }
     }
 
@@ -100,7 +100,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 TempRef::Lvalue(lvalue) =>
                     lvalue,
                 TempRef::Operand(..) =>
-                    tcx.sess.bug(&format!("using operand temp {:?} as lvalue", lvalue)),
+                    bug!("using operand temp {:?} as lvalue", lvalue),
             },
             mir::Lvalue::Arg(index) => self.args[index as usize],
             mir::Lvalue::Static(def_id) => {
diff --git a/src/librustc_trans/mir/mod.rs b/src/librustc_trans/mir/mod.rs
index 61536f3ecae..a7e57fc714b 100644
--- a/src/librustc_trans/mir/mod.rs
+++ b/src/librustc_trans/mir/mod.rs
@@ -180,7 +180,7 @@ fn arg_value_refs<'bcx, 'tcx>(bcx: &BlockAndBuilder<'bcx, 'tcx>,
 
             let tupled_arg_tys = match arg_ty.sty {
                 ty::TyTuple(ref tys) => tys,
-                _ => unreachable!("spread argument isn't a tuple?!")
+                _ => bug!("spread argument isn't a tuple?!")
             };
 
             let lltemp = bcx.with_block(|bcx| {
diff --git a/src/librustc_trans/mir/operand.rs b/src/librustc_trans/mir/operand.rs
index 3b909353f73..c15d6cd5b24 100644
--- a/src/librustc_trans/mir/operand.rs
+++ b/src/librustc_trans/mir/operand.rs
@@ -79,7 +79,7 @@ impl<'tcx> OperandRef<'tcx> {
     pub fn immediate(self) -> ValueRef {
         match self.val {
             OperandValue::Immediate(s) => s,
-            _ => unreachable!()
+            _ => bug!()
         }
     }
 }
@@ -124,8 +124,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                             return o;
                         }
                         TempRef::Operand(None) => {
-                            bcx.tcx().sess.bug(
-                                &format!("use of {:?} before def", lvalue));
+                            bug!("use of {:?} before def", lvalue);
                         }
                         TempRef::Lvalue(..) => {
                             // use path below
diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs
index 1396883120b..3f7a6c5f180 100644
--- a/src/librustc_trans/mir/rvalue.rs
+++ b/src/librustc_trans/mir/rvalue.rs
@@ -70,7 +70,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                 let operand = self.trans_operand(&bcx, source);
                 bcx.with_block(|bcx| {
                     match operand.val {
-                        OperandValue::FatPtr(..) => unreachable!(),
+                        OperandValue::FatPtr(..) => bug!(),
                         OperandValue::Immediate(llval) => {
                             // unsize from an immediate structure. We don't
                             // really need a temporary alloca here, but
@@ -185,7 +185,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                     ty::TySlice(_) | ty::TyStr => {
                         (bcx.gepi(input.llval, &[from_start]), input.llextra)
                     }
-                    _ => unreachable!("cannot slice {}", ty)
+                    _ => bug!("cannot slice {}", ty)
                 };
                 let adj = C_uint(ccx, from_start + from_end);
                 let lllen1 = bcx.sub(lllen, adj);
@@ -246,7 +246,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                         .reify(bcx.ccx()).val)
                             }
                             _ => {
-                                unreachable!("{} cannot be reified to a fn ptr", operand.ty)
+                                bug!("{} cannot be reified to a fn ptr", operand.ty)
                             }
                         }
                     }
@@ -279,9 +279,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                 OperandValue::FatPtr(lldata, llextra)
                             }
                             OperandValue::Ref(_) => {
-                                bcx.sess().bug(
-                                    &format!("by-ref operand {:?} in trans_rvalue_operand",
-                                             operand));
+                                bug!("by-ref operand {:?} in trans_rvalue_operand",
+                                     operand);
                             }
                         }
                     }
@@ -341,9 +340,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                 bcx.fptosi(llval, ll_t_out),
                             (CastTy::Float, CastTy::Int(_)) =>
                                 bcx.fptoui(llval, ll_t_out),
-                            _ => bcx.ccx().sess().bug(
-                                &format!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
-                            )
+                            _ => bug!("unsupported cast: {:?} to {:?}", operand.ty, cast_ty)
                         };
                         OperandValue::Immediate(newval)
                     }
@@ -364,7 +361,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                 OperandValue::Immediate(llval)
                             }
                         } else {
-                            panic!("Unexpected non-FatPtr operand")
+                            bug!("Unexpected non-FatPtr operand")
                         }
                     }
                 };
@@ -425,7 +422,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                                        DebugLoc::None)
                             })
                         }
-                        _ => unreachable!()
+                        _ => bug!()
                     }
 
                 } else {
@@ -489,7 +486,8 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
             mir::Rvalue::Aggregate(..) |
             mir::Rvalue::Slice { .. } |
             mir::Rvalue::InlineAsm { .. } => {
-                bcx.tcx().sess.bug(&format!("cannot generate operand from rvalue {:?}", rvalue));
+                bug!("cannot generate operand from rvalue {:?}", rvalue);
+
             }
         }
     }
diff --git a/src/librustc_trans/mir/statement.rs b/src/librustc_trans/mir/statement.rs
index d291bc19db5..1d85ac6fb79 100644
--- a/src/librustc_trans/mir/statement.rs
+++ b/src/librustc_trans/mir/statement.rs
@@ -36,9 +36,9 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
                                 bcx
                             }
                             TempRef::Operand(Some(_)) => {
-                                bcx.tcx().sess.span_bug(
-                                    statement.span,
-                                    &format!("operand {:?} already assigned", rvalue));
+                                span_bug!(statement.span,
+                                          "operand {:?} already assigned",
+                                          rvalue);
                             }
                         }
                     }
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 04a07bdf1ce..554e1948fe9 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -149,13 +149,13 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     Disr::from(inlined_variant_def(ccx, fn_node_id).disr_val)
                 }
                 hir_map::NodeStructCtor(_) => Disr(0),
-                _ => unreachable!()
+                _ => bug!()
             };
             attributes::inline(lldecl, attributes::InlineAttr::Hint);
             base::trans_ctor_shim(ccx, fn_node_id, disr, psubsts, lldecl);
         }
 
-        _ => unreachable!("can't monomorphize a {:?}", map_node)
+        _ => bug!("can't monomorphize a {:?}", map_node)
     };
 
     ccx.monomorphizing().borrow_mut().insert(fn_id, depth);
diff --git a/src/librustc_trans/tvec.rs b/src/librustc_trans/tvec.rs
index 56ba1b02426..b9af02ac529 100644
--- a/src/librustc_trans/tvec.rs
+++ b/src/librustc_trans/tvec.rs
@@ -183,8 +183,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     }
                 }
                 _ => {
-                    bcx.tcx().sess.span_bug(content_expr.span,
-                                            "unexpected evec content");
+                    span_bug!(content_expr.span, "unexpected evec content");
                 }
             }
         }
@@ -236,8 +235,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
         }
         _ => {
-            bcx.tcx().sess.span_bug(content_expr.span,
-                                    "unexpected vec content");
+            span_bug!(content_expr.span, "unexpected vec content");
         }
     }
 }
@@ -264,8 +262,7 @@ fn elements_required(bcx: Block, content_expr: &hir::Expr) -> usize {
             match lit.node {
                 ast::LitKind::Str(ref s, _) => s.len(),
                 _ => {
-                    bcx.tcx().sess.span_bug(content_expr.span,
-                                            "unexpected evec content")
+                    span_bug!(content_expr.span, "unexpected evec content")
                 }
             }
         },
@@ -273,8 +270,7 @@ fn elements_required(bcx: Block, content_expr: &hir::Expr) -> usize {
         hir::ExprRepeat(_, ref count_expr) => {
             eval_repeat_count(bcx.tcx(), &count_expr)
         }
-        _ => bcx.tcx().sess.span_bug(content_expr.span,
-                                     "unexpected vec content")
+        _ => span_bug!(content_expr.span, "unexpected vec content")
     }
 }
 
@@ -298,8 +294,6 @@ pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                     llval: ValueRef,
                                     vec_ty: Ty<'tcx>)
                                     -> (ValueRef, ValueRef) {
-    let ccx = bcx.ccx();
-
     match vec_ty.sty {
         ty::TyArray(_, n) => get_fixed_base_and_len(bcx, llval, n),
         ty::TySlice(_) | ty::TyStr => {
@@ -317,7 +311,7 @@ pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
             get_base_and_len(bcx, inner, ty)
         },
-        _ => ccx.sess().bug("unexpected type in get_base_and_len"),
+        _ => bug!("unexpected type in get_base_and_len"),
     }
 }
 
diff --git a/src/librustc_trans/type_.rs b/src/librustc_trans/type_.rs
index 910a1c7f729..35a60cd5422 100644
--- a/src/librustc_trans/type_.rs
+++ b/src/librustc_trans/type_.rs
@@ -124,7 +124,7 @@ impl Type {
         match &ccx.tcx().sess.target.target.target_pointer_width[..] {
             "32" => Type::i32(ccx),
             "64" => Type::i64(ccx),
-            tws => panic!("Unsupported target word size for int: {}", tws),
+            tws => bug!("Unsupported target word size for int: {}", tws),
         }
     }
 
@@ -288,7 +288,7 @@ impl Type {
             Double => 64,
             X86_FP80 => 80,
             FP128 | PPC_FP128 => 128,
-            _ => panic!("llvm_float_width called on a non-float type")
+            _ => bug!("llvm_float_width called on a non-float type")
         }
     }
 
diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs
index 02f659fdc2e..8b1aaafab58 100644
--- a/src/librustc_trans/type_of.rs
+++ b/src/librustc_trans/type_of.rs
@@ -113,10 +113,9 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
         }
 
         ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError => {
-            cx.sess().bug(&format!("fictitious type {:?} in sizing_type_of()",
-                                   t))
+            bug!("fictitious type {:?} in sizing_type_of()", t)
         }
-        ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => unreachable!()
+        ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => bug!()
     };
 
     debug!("--> mapped t={:?} to llsizingty={:?}", t, llsizingty);
@@ -132,7 +131,7 @@ fn unsized_info_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type
             Type::uint_from_ty(ccx, ast::UintTy::Us)
         }
         ty::TyTrait(_) => Type::vtable_ptr(ccx),
-        _ => unreachable!("Unexpected tail in unsized_info_ty: {:?} for ty={:?}",
+        _ => bug!("Unexpected tail in unsized_info_ty: {:?} for ty={:?}",
                           unsized_part, ty)
     }
 }
@@ -296,10 +295,10 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           }
       }
 
-      ty::TyInfer(..) => cx.sess().bug("type_of with TyInfer"),
-      ty::TyProjection(..) => cx.sess().bug("type_of with TyProjection"),
-      ty::TyParam(..) => cx.sess().bug("type_of with ty_param"),
-      ty::TyError => cx.sess().bug("type_of with TyError"),
+      ty::TyInfer(..) => bug!("type_of with TyInfer"),
+      ty::TyProjection(..) => bug!("type_of with TyProjection"),
+      ty::TyParam(..) => bug!("type_of with ty_param"),
+      ty::TyError => bug!("type_of with TyError"),
     };
 
     debug!("--> mapped t={:?} to llty={:?}", t, llty);
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index b7d00716f02..d925ff9fa3c 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -161,7 +161,7 @@ pub fn ast_region_to_region(tcx: &TyCtxt, lifetime: &hir::Lifetime)
     let r = match tcx.named_region_map.get(&lifetime.id) {
         None => {
             // should have been recorded by the `resolve_lifetime` pass
-            tcx.sess.span_bug(lifetime.span, "unresolved lifetime");
+            span_bug!(lifetime.span, "unresolved lifetime");
         }
 
         Some(&rl::DefStaticRegion) => {
@@ -485,7 +485,7 @@ fn create_substs_for_ast_path<'tcx>(
                 substs.types.push(TypeSpace, default);
             }
         } else {
-            tcx.sess.span_bug(span, "extra parameter without default");
+            span_bug!(span, "extra parameter without default");
         }
     }
 
@@ -839,7 +839,7 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
         Err(ErrorReported) => {
             // No convenient way to recover from a cycle here. Just bail. Sorry!
             this.tcx().sess.abort_if_errors();
-            this.tcx().sess.bug("ErrorReported returned, but no errors reports?")
+            bug!("ErrorReported returned, but no errors reports?")
         }
     };
 
@@ -1353,7 +1353,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                       .expect("missing associated type");
                 tcx.map.local_def_id(item.id)
             }
-            _ => unreachable!()
+            _ => bug!()
         }
     } else {
         let trait_items = tcx.trait_items(trait_did);
@@ -1496,7 +1496,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                     ty
                 }
             } else {
-                tcx.sess.span_bug(span, "self type has not been fully resolved")
+                span_bug!(span, "self type has not been fully resolved")
             }
         }
         Def::SelfTy(Some(_), None) => {
@@ -1654,7 +1654,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                     depth: path.segments.len()
                 }
             } else {
-                tcx.sess.span_bug(ast_ty.span, &format!("unbound path {:?}", ast_ty))
+                span_bug!(ast_ty.span, "unbound path {:?}", ast_ty)
             };
             let def = path_res.base_def;
             let base_ty_end = path.segments.len() - path_res.depth;
@@ -1961,7 +1961,7 @@ pub fn ty_of_closure<'tcx>(
             ty::FnConverging(this.ty_infer(None, None, None, decl.output.span())),
         hir::Return(ref output) =>
             ty::FnConverging(ast_ty_to_ty(this, &rb, &output)),
-        hir::DefaultReturn(..) => unreachable!(),
+        hir::DefaultReturn(..) => bug!(),
         hir::NoReturn(..) => ty::FnDiverging
     };
 
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index f8fa9c8e9b6..6dad3ff850b 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -413,8 +413,7 @@ fn check_assoc_item_is_const(pcx: &pat_ctxt, def: Def, span: Span) -> bool {
             false
         }
         _ => {
-            pcx.fcx.ccx.tcx.sess.span_bug(span, "non-associated item in
-                                                 check_assoc_item_is_const");
+            span_bug!(span, "non-associated item in check_assoc_item_is_const");
         }
     }
 }
@@ -588,7 +587,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx hir::Pat,
     let pat_ty = pcx.fcx.instantiate_type(def.def_id(), path);
     let item_substs = match pat_ty.sty {
         ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
-        _ => tcx.sess.span_bug(pat.span, "struct variant is not an ADT")
+        _ => span_bug!(pat.span, "struct variant is not an ADT")
     };
     demand::eqtype(fcx, pat.span, expected, pat_ty);
     check_struct_pat_fields(pcx, pat.span, fields, variant, &item_substs, etc);
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 4e582033c8b..bedf4753313 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -397,7 +397,7 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
                 write_overloaded_call_method_map(fcx, self.call_expr, method_callee);
             }
             None => {
-                fcx.tcx().sess.span_bug(
+                span_bug!(
                     self.call_expr.span,
                     "failed to find an overloaded call trait for closure call");
             }
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 7ca4251e4c8..d743a036040 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -139,7 +139,7 @@ impl<'tcx> CastCheck<'tcx> {
                             CastError::NeedViaThinPtr => "a thin pointer",
                             CastError::NeedViaInt => "an integer",
                             CastError::NeedViaUsize => "a usize",
-                            _ => unreachable!()
+                            _ => bug!()
                         }))
                     .emit();
             }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index e36da1a568a..70467e2d2dd 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -372,8 +372,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         }
         let r_borrow = match ty.sty {
             ty::TyRef(r_borrow, _) => r_borrow,
-            _ => self.tcx().sess.span_bug(span,
-                                          &format!("expected a ref type, got {:?}", ty))
+            _ => span_bug!(span, "expected a ref type, got {:?}", ty)
         };
         let autoref = Some(AutoPtr(r_borrow, mt_b.mutbl));
         debug!("coerce_borrowed_pointer: succeeded ty={:?} autoderefs={:?} autoref={:?}",
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index bf2388ab793..1f1bba509e0 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -62,9 +62,9 @@ pub fn check_drop_impl(tcx: &TyCtxt, drop_impl_did: DefId) -> Result<(), ()> {
             // Destructors only work on nominal types.  This was
             // already checked by coherence, so we can panic here.
             let span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
-            tcx.sess.span_bug(
-                span, &format!("should have been rejected by coherence check: {}",
-                               dtor_self_type));
+            span_bug!(span,
+                      "should have been rejected by coherence check: {}",
+                      dtor_self_type);
         }
     }
 }
@@ -276,8 +276,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
            typ, scope);
 
     let parent_scope = rcx.tcx().region_maps.opt_encl_scope(scope).unwrap_or_else(|| {
-        rcx.tcx().sess.span_bug(
-            span, &format!("no enclosing scope found for scope: {:?}", scope))
+        span_bug!(span, "no enclosing scope found for scope: {:?}", scope)
     });
 
     let result = iterate_over_potentially_unsafe_regions_in_type(
@@ -493,7 +492,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
         }
 
         // these are always dtorck
-        ty::TyTrait(..) | ty::TyProjection(_) => unreachable!(),
+        ty::TyTrait(..) | ty::TyProjection(_) => bug!(),
     }
 }
 
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 310245f0a0e..f90a5696539 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -300,10 +300,10 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         match result {
             Some(r) => r,
             None => {
-                self.tcx().sess.span_bug(
+                span_bug!(
                     self.span,
-                    &format!("self-type `{}` for ObjectPick never dereferenced to an object",
-                            self_ty))
+                    "self-type `{}` for ObjectPick never dereferenced to an object",
+                    self_ty)
             }
         }
     }
@@ -372,10 +372,10 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         match self.fcx.mk_subty(false, TypeOrigin::Misc(self.span), self_ty, method_self_ty) {
             Ok(_) => {}
             Err(_) => {
-                self.tcx().sess.span_bug(
+                span_bug!(
                     self.span,
-                    &format!("{} was a subtype of {} but now is not?",
-                             self_ty, method_self_ty));
+                    "{} was a subtype of {} but now is not?",
+                    self_ty, method_self_ty);
             }
         }
     }
@@ -550,15 +550,15 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                                 }))
                             }
                             Some(_) => {
-                                self.tcx().sess.span_bug(
+                                span_bug!(
                                     base_expr.span,
-                                    &format!("unexpected adjustment autoref {:?}",
-                                            adr));
+                                    "unexpected adjustment autoref {:?}",
+                                    adr);
                             }
                         },
                         None => (0, None),
                         Some(_) => {
-                            self.tcx().sess.span_bug(
+                            span_bug!(
                                 base_expr.span,
                                 "unexpected adjustment type");
                         }
@@ -646,12 +646,12 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
 
         // must be exactly one trait ref or we'd get an ambig error etc
         if upcast_trait_refs.len() != 1 {
-            self.tcx().sess.span_bug(
+            span_bug!(
                 self.span,
-                &format!("cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
-                         source_trait_ref,
-                         target_trait_def_id,
-                         upcast_trait_refs));
+                "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
+                source_trait_ref,
+                target_trait_def_id,
+                upcast_trait_refs);
         }
 
         upcast_trait_refs.into_iter().next().unwrap()
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 8c8d02bd3e6..43a18d2c102 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -302,21 +302,19 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         }
 
                         _ => {
-                            fcx.tcx().sess.span_bug(
+                            span_bug!(
                                 span,
-                                &format!(
-                                    "trait method is &self but first arg is: {}",
-                                    transformed_self_ty));
+                                "trait method is &self but first arg is: {}",
+                                transformed_self_ty);
                         }
                     }
                 }
 
                 _ => {
-                    fcx.tcx().sess.span_bug(
+                    span_bug!(
                         span,
-                        &format!(
-                            "unexpected explicit self type in operator method: {:?}",
-                            method_ty.explicit_self));
+                        "unexpected explicit self type in operator method: {:?}",
+                        method_ty.explicit_self);
                 }
             }
         }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 477b46ce4ce..c4a8022071b 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -877,8 +877,8 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                         match tcx.trait_id_of_impl(impl_id) {
                             Some(id) => id,
                             None =>
-                                tcx.sess.span_bug(span,
-                                                  "found inherent method when looking at traits")
+                                span_bug!(span,
+                                          "found inherent method when looking at traits")
                         }
                     }
                 }
@@ -889,7 +889,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             }
             Some(Err(MethodError::ClosureAmbiguity(..))) => {
                 // this error only occurs when assembling candidates
-                tcx.sess.span_bug(span, "encountered ClosureAmbiguity from pick_core");
+                span_bug!(span, "encountered ClosureAmbiguity from pick_core");
             }
             _ => vec![],
         };
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 9ed82fbab46..6c3469c9d72 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -463,8 +463,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
         }
-        _ => ccx.tcx.sess.impossible_case(body.span,
-                                 "check_bare_fn: function type expected")
+        _ => span_bug!(body.span, "check_bare_fn: function type expected")
     }
 }
 
@@ -946,7 +945,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 hir::ImplItemKind::Const(..) => {
                     let impl_const = match ty_impl_item {
                         ty::ConstTraitItem(ref cti) => cti,
-                        _ => tcx.sess.span_bug(impl_item.span, "non-const impl-item for const")
+                        _ => span_bug!(impl_item.span, "non-const impl-item for const")
                     };
 
                     // Find associated const definition.
@@ -969,7 +968,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
                     let impl_method = match ty_impl_item {
                         ty::MethodTraitItem(ref mti) => mti,
-                        _ => tcx.sess.span_bug(impl_item.span, "non-method impl-item for method")
+                        _ => span_bug!(impl_item.span, "non-method impl-item for method")
                     };
 
                     if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
@@ -990,7 +989,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 hir::ImplItemKind::Type(_) => {
                     let impl_type = match ty_impl_item {
                         ty::TypeTraitItem(ref tti) => tti,
-                        _ => tcx.sess.span_bug(impl_item.span, "non-type impl-item for type")
+                        _ => span_bug!(impl_item.span, "non-type impl-item for type")
                     };
 
                     if let &ty::TypeTraitItem(ref at) = ty_trait_item {
@@ -1567,8 +1566,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         match self.inh.tables.borrow().node_types.get(&ex.id) {
             Some(&t) => t,
             None => {
-                self.tcx().sess.bug(&format!("no type for expr in fcx {}",
-                                            self.tag()));
+                bug!("no type for expr in fcx {}", self.tag());
             }
         }
     }
@@ -1593,10 +1591,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Some(&t) => t,
             None if self.err_count_since_creation() != 0 => self.tcx().types.err,
             None => {
-                self.tcx().sess.bug(
-                    &format!("no type for node {}: {} in fcx {}",
-                            id, self.tcx().map.node_to_string(id),
-                            self.tag()));
+                bug!("no type for node {}: {} in fcx {}",
+                     id, self.tcx().map.node_to_string(id),
+                     self.tag());
             }
         }
     }
@@ -2386,8 +2383,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 fty.sig.0.output
             }
             _ => {
-                fcx.tcx().sess.span_bug(callee_expr.span,
-                                        "method without bare fn type");
+                span_bug!(callee_expr.span, "method without bare fn type");
             }
         }
     }
@@ -3139,7 +3135,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         let tcx = fcx.ccx.tcx;
         let substs = match adt_ty.sty {
             ty::TyStruct(_, substs) | ty::TyEnum(_, substs) => substs,
-            _ => tcx.sess.span_bug(span, "non-ADT passed to check_expr_struct_fields")
+            _ => span_bug!(span, "non-ADT passed to check_expr_struct_fields")
         };
 
         let mut remaining_fields = FnvHashMap();
@@ -3400,8 +3396,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     depth: path.segments.len()
                 }
             } else {
-              tcx.sess.span_bug(expr.span,
-                                &format!("unbound path {:?}", expr))
+              span_bug!(expr.span, "unbound path {:?}", expr)
           };
 
           if let Some((opt_ty, segments, def)) =
@@ -4224,7 +4219,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         Def::Label(..) |
         Def::SelfTy(..) |
         Def::Err => {
-            fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
+            span_bug!(sp, "expected value, found {:?}", defn);
         }
     }
 }
@@ -4485,11 +4480,10 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
         let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
         if fcx.mk_subty(false, TypeOrigin::Misc(span), self_ty, impl_ty).is_err() {
-            fcx.tcx().sess.span_bug(span,
-            &format!(
+            span_bug!(span,
                 "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
                 self_ty,
-                impl_ty));
+                impl_ty);
         }
     }
 
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 281564af615..494135ee3ff 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -270,8 +270,9 @@ fn name_and_trait_def_id(fcx: &FnCtxt,
             hir::BiShr => ("shr_assign", lang.shr_assign_trait()),
             hir::BiLt | hir::BiLe | hir::BiGe | hir::BiGt | hir::BiEq | hir::BiNe | hir::BiAnd |
             hir::BiOr => {
-                fcx.tcx().sess.span_bug(op.span, &format!("impossible assignment operation: {}=",
-                                        hir_util::binop_to_string(op.node)))
+                span_bug!(op.span,
+                          "impossible assignment operation: {}=",
+                          hir_util::binop_to_string(op.node))
             }
         }
     } else {
@@ -293,7 +294,7 @@ fn name_and_trait_def_id(fcx: &FnCtxt,
             hir::BiEq => ("eq", lang.eq_trait()),
             hir::BiNe => ("ne", lang.eq_trait()),
             hir::BiAnd | hir::BiOr => {
-                fcx.tcx().sess.span_bug(op.span, "&& and || are not overloadable")
+                span_bug!(op.span, "&& and || are not overloadable")
             }
         }
     }
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 533d24686e7..283245bd6f4 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -298,8 +298,7 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
             match fn_sig_map.get(&id) {
                 Some(f) => f.clone(),
                 None => {
-                    self.tcx().sess.bug(
-                        &format!("No fn-sig entry for id={}", id));
+                    bug!("No fn-sig entry for id={}", id);
                 }
             }
         };
@@ -446,8 +445,8 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
         let subject_node_id = match self.subject {
             Subject(s) => s,
             SubjectNode::None => {
-                self.tcx().sess.bug("cannot resolve_regions_and_report_errors \
-                                     without subject node");
+                bug!("cannot resolve_regions_and_report_errors \
+                      without subject node");
             }
         };
 
@@ -886,9 +885,10 @@ fn constrain_callee(rcx: &mut Rcx,
             // this should not happen, but it does if the program is
             // erroneous
             //
-            // tcx.sess.span_bug(
+            // bug!(
             //     callee_expr.span,
-            //     format!("Calling non-function: {}", callee_ty));
+            //     "Calling non-function: {}",
+            //     callee_ty);
         }
     }
 }
@@ -986,10 +986,10 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                 let (m, r) = match self_ty.sty {
                     ty::TyRef(r, ref m) => (m.mutbl, r),
                     _ => {
-                        rcx.tcx().sess.span_bug(
+                        span_bug!(
                             deref_expr.span,
-                            &format!("bad overloaded deref type {:?}",
-                                     method.ty))
+                            "bad overloaded deref type {:?}",
+                            method.ty)
                     }
                 };
 
@@ -1014,7 +1014,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                           return_type, r_deref_expr);
                         return_type
                     }
-                    ty::FnDiverging => unreachable!()
+                    ty::FnDiverging => bug!()
                 }
             }
             None => derefd_ty
@@ -1057,12 +1057,10 @@ fn check_safety_of_rvalue_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 't
                 }
                 ty::ReStatic => {}
                 region => {
-                    rcx.tcx()
-                       .sess
-                       .span_bug(span,
-                                 &format!("unexpected rvalue region in rvalue \
-                                           destructor safety checking: `{:?}`",
-                                          region));
+                    span_bug!(span,
+                              "unexpected rvalue region in rvalue \
+                               destructor safety checking: `{:?}`",
+                              region);
                 }
             }
         }
@@ -1394,10 +1392,7 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                     infer::ReborrowUpvar(span, *upvar_id)
                 }
                 _ => {
-                    rcx.tcx().sess.span_bug(
-                        span,
-                        &format!("Illegal upvar id: {:?}",
-                                upvar_id));
+                    span_bug!( span, "Illegal upvar id: {:?}", upvar_id);
                 }
             }
         }
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 69e49e6a986..7d51d5ec7f7 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -209,10 +209,10 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
         let closure_substs = match self.fcx.node_ty(id).sty {
             ty::TyClosure(_, ref substs) => substs,
             ref t => {
-                self.fcx.tcx().sess.span_bug(
+                span_bug!(
                     span,
-                    &format!("type of closure expr {:?} is not a closure {:?}",
-                             id, t));
+                    "type of closure expr {:?} is not a closure {:?}",
+                    id, t);
             }
         };
 
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 047dfec1796..68c9816b48c 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -257,7 +257,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             let bare_fn_ty = match item_ty.sty {
                 ty::TyFnDef(_, _, ref bare_fn_ty) => bare_fn_ty,
                 _ => {
-                    this.tcx().sess.span_bug(item.span, "Fn item without fn type");
+                    span_bug!(item.span, "Fn item without fn type");
                 }
             };
 
@@ -473,7 +473,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         let name = match space {
             TypeSpace => ast_generics.ty_params[index].name,
             SelfSpace => special_idents::type_self.name,
-            FnSpace => self.tcx().sess.bug("Fn space occupied?"),
+            FnSpace => bug!("Fn space occupied?"),
         };
 
         ty::ParamTy { space: space, idx: index as u32, name: name }
@@ -489,7 +489,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         match space {
             TypeSpace => ast_generics.ty_params[index].span,
             SelfSpace => item.span,
-            FnSpace => self.tcx().sess.span_bug(item.span, "Fn space occupied?"),
+            FnSpace => span_bug!(item.span, "Fn space occupied?"),
         }
     }
 
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index c3b46ef83ac..f9a4cfadc0b 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -77,10 +77,10 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
         TyInfer(..) | TyClosure(..) => {
             // `ty` comes from a user declaration so we should only expect types
             // that the user can type
-            inference_context.tcx.sess.span_bug(
+            span_bug!(
                 span,
-                &format!("coherence encountered unexpected type searching for base type: {}",
-                         ty));
+                "coherence encountered unexpected type searching for base type: {}",
+                ty);
         }
     }
 }
@@ -219,9 +219,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 }).collect()
             }
             _ => {
-                self.crate_context.tcx.sess.span_bug(item.span,
-                                                     "can't convert a non-impl \
-                                                      to an impl");
+                span_bug!(item.span, "can't convert a non-impl to an impl");
             }
         }
     }
@@ -263,13 +261,12 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                                           "the Drop trait may only be implemented on structures");
                             }
                             _ => {
-                                tcx.sess.bug("didn't find impl in ast \
-                                              map");
+                                bug!("didn't find impl in ast map");
                             }
                         }
                     } else {
-                        tcx.sess.bug("found external impl of Drop trait on \
-                                      something other than a struct");
+                        bug!("found external impl of Drop trait on \
+                              :omething other than a struct");
                     }
                 }
             }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index a9ef0fce880..59546f619c0 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -274,7 +274,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
         if let Some(trait_id) = tcx.map.as_local_node_id(trait_id) {
             let item = match tcx.map.get(trait_id) {
                 hir_map::NodeItem(item) => item,
-                _ => tcx.sess.bug(&format!("get_trait_def({:?}): not an item", trait_id))
+                _ => bug!("get_trait_def({:?}): not an item", trait_id)
             };
 
             trait_def_of_item(self, &item)
@@ -1165,13 +1165,13 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
     let superpredicates = superpredicates.unwrap_or_else(|| {
         let item = match ccx.tcx.map.get(trait_node_id) {
             hir_map::NodeItem(item) => item,
-            _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
+            _ => bug!("trait_node_id {} is not an item", trait_node_id)
         };
 
         let (generics, bounds) = match item.node {
             hir::ItemTrait(_, ref generics, ref supertraits, _) => (generics, supertraits),
-            _ => tcx.sess.span_bug(item.span,
-                                   "ensure_super_predicates_step invoked on non-trait"),
+            _ => span_bug!(item.span,
+                           "ensure_super_predicates_step invoked on non-trait"),
         };
 
         // In-scope when converting the superbounds for `Trait` are
@@ -1237,7 +1237,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let (unsafety, generics, items) = match it.node {
         hir::ItemTrait(unsafety, ref generics, _, ref items) => (unsafety, generics, items),
-        _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"),
+        _ => span_bug!(it.span, "trait_def_of_item invoked on non-trait"),
     };
 
     let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar");
@@ -1317,12 +1317,12 @@ fn trait_defines_associated_type_named(ccx: &CrateCtxt,
 {
     let item = match ccx.tcx.map.get(trait_node_id) {
         hir_map::NodeItem(item) => item,
-        _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not an item", trait_node_id))
+        _ => bug!("trait_node_id {} is not an item", trait_node_id)
     };
 
     let trait_items = match item.node {
         hir::ItemTrait(_, _, _, ref trait_items) => trait_items,
-        _ => ccx.tcx.sess.bug(&format!("trait_node_id {} is not a trait", trait_node_id))
+        _ => bug!("trait_node_id {} is not a trait", trait_node_id)
     };
 
     trait_items.iter().any(|trait_item| {
@@ -1342,9 +1342,10 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item)
     let (generics, items) = match it.node {
         hir::ItemTrait(_, ref generics, _, ref items) => (generics, items),
         ref s => {
-            tcx.sess.span_bug(
+            span_bug!(
                 it.span,
-                &format!("trait_def_of_item invoked on {:?}", s));
+                "trait_def_of_item invoked on {:?}",
+                s);
         }
     };
 
@@ -1421,9 +1422,8 @@ fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                 type_scheme_of_foreign_item(ccx, &foreign_item, abi)
             }
             x => {
-                ccx.tcx.sess.bug(&format!("unexpected sort of node \
-                                           in get_item_type_scheme(): {:?}",
-                                          x));
+                bug!("unexpected sort of node in get_item_type_scheme(): {:?}",
+                     x);
             }
         }
     } else {
@@ -1489,10 +1489,10 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         hir::ItemForeignMod(..) |
         hir::ItemExternCrate(..) |
         hir::ItemUse(..) => {
-            tcx.sess.span_bug(
+            span_bug!(
                 it.span,
-                &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
-                         it.node));
+                "compute_type_scheme_of_item: unexpected item type: {:?}",
+                it.node);
         }
     }
 }
@@ -1528,10 +1528,10 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         hir::ItemImpl(..) |
         hir::ItemMod(..) |
         hir::ItemForeignMod(..) => {
-            tcx.sess.span_bug(
+            span_bug!(
                 it.span,
-                &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
-                         it.node));
+                "compute_type_scheme_of_item: unexpected item type: {:?}",
+                it.node);
         }
     };
 
@@ -1836,9 +1836,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
             &hir::WherePredicate::EqPredicate(ref eq_pred) => {
                 // FIXME(#20041)
-                tcx.sess.span_bug(eq_pred.span,
-                                    "Equality constraints are not yet \
-                                        implemented (#20041)")
+                span_bug!(eq_pred.span,
+                         "Equality constraints are not yet \
+                          implemented (#20041)")
             }
         }
     }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index c3ba9182343..fa23445fe63 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -88,7 +88,7 @@ This API is completely unstable and subject to change.
 
 extern crate arena;
 extern crate fmt_macros;
-extern crate rustc;
+#[macro_use] extern crate rustc;
 extern crate rustc_platform_intrinsics as intrinsics;
 extern crate rustc_front;
 extern crate rustc_back;
@@ -258,9 +258,9 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 });
         }
         _ => {
-            tcx.sess.span_bug(main_span,
-                              &format!("main has a non-function type: found `{}`",
-                                       main_t));
+            span_bug!(main_span,
+                      "main has a non-function type: found `{}`",
+                      main_t);
         }
     }
 }
@@ -310,9 +310,9 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
 
         }
         _ => {
-            tcx.sess.span_bug(start_span,
-                              &format!("start has a non-function type: found `{}`",
-                                       start_t));
+            span_bug!(start_span,
+                      "start has a non-function type: found `{}`",
+                      start_t);
         }
     }
 }
@@ -325,7 +325,7 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
             Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
             Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
             Some(config::EntryNone) => {}
-            None => tcx.sess.bug("entry function without a type")
+            None => bug!("entry function without a type")
         },
         None => {}
     }
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 1ed355c90a5..50c99e33b44 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -135,9 +135,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         match self.terms_cx.inferred_map.get(&param_id) {
             Some(&index) => index,
             None => {
-                self.tcx().sess.bug(&format!(
-                        "no inferred index entry for {}",
-                        self.tcx().map.node_to_string(param_id)));
+                bug!("no inferred index entry for {}",
+                     self.tcx().map.node_to_string(param_id));
             }
         }
     }
@@ -148,7 +147,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         match tcx.named_region_map.get(&param_id) {
             Some(&rl::DefEarlyBoundRegion(_, _, lifetime_decl_id))
                 => lifetime_decl_id,
-            Some(_) => panic!("should not encounter non early-bound cases"),
+            Some(_) => bug!("should not encounter non early-bound cases"),
 
             // The lookup should only fail when `param_id` is
             // itself a lifetime binding: use it as the decl_id.
@@ -173,13 +172,13 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             assert!(is_lifetime(&tcx.map, param_id));
             let parent_id = tcx.map.get_parent(decl_id);
             let parent = tcx.map.find(parent_id).unwrap_or_else(
-                || panic!("tcx.map missing entry for id: {}", parent_id));
+                || bug!("tcx.map missing entry for id: {}", parent_id));
 
             let is_inferred;
             macro_rules! cannot_happen { () => { {
-                panic!("invalid parent: {} for {}",
-                      tcx.map.node_to_string(parent_id),
-                      tcx.map.node_to_string(param_id));
+                bug!("invalid parent: {} for {}",
+                     tcx.map.node_to_string(parent_id),
+                     tcx.map.node_to_string(param_id));
             } } }
 
             match parent {
@@ -328,7 +327,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             }
 
             ty::TyClosure(..) => {
-                self.tcx().sess.bug("Unexpected closure type in variance computation");
+                bug!("Unexpected closure type in variance computation");
             }
 
             ty::TyRef(region, ref mt) => {
@@ -440,9 +439,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             }
 
             ty::TyInfer(..) => {
-                self.tcx().sess.bug(
-                    &format!("unexpected type encountered in \
-                              variance inference: {}", ty));
+                bug!("unexpected type encountered in \
+                      variance inference: {}", ty);
             }
         }
     }
@@ -525,11 +523,9 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
             ty::ReSkolemized(..) | ty::ReEmpty => {
                 // We don't expect to see anything but 'static or bound
                 // regions when visiting member types or method types.
-                self.tcx()
-                    .sess
-                    .bug(&format!("unexpected region encountered in variance \
-                                  inference: {:?}",
-                                 region));
+                bug!("unexpected region encountered in variance \
+                      inference: {:?}",
+                     region);
             }
         }
     }