diff --git a/doc/lib/codemirror-rust.js b/doc/lib/codemirror-rust.js
index 727882d3099..052669be6f5 100644
--- a/doc/lib/codemirror-rust.js
+++ b/doc/lib/codemirror-rust.js
@@ -2,7 +2,7 @@ CodeMirror.defineMode("rust", function() {
   var indentUnit = 4, altIndentUnit = 2;
   var valKeywords = {
     "if": "if-style", "while": "if-style", "loop": "if-style", "else": "else-style",
-    "do": "else-style", "return": "else-style", "fail": "else-style",
+    "do": "else-style", "return": "else-style",
     "break": "atom", "cont": "atom", "const": "let", "resource": "fn",
     "let": "let", "fn": "fn", "for": "for", "match": "match", "trait": "trait",
     "impl": "impl", "type": "type", "enum": "enum", "struct": "atom", "mod": "mod",
diff --git a/doc/rust.md b/doc/rust.md
index 0a2544e4e18..7d4ec54aff5 100644
--- a/doc/rust.md
+++ b/doc/rust.md
@@ -216,7 +216,7 @@ break
 const copy
 do drop
 else enum extern
-fail false fn for
+false fn for
 if impl
 let log loop
 match mod move mut
@@ -692,15 +692,15 @@ mod math {
     type complex = (f64, f64);
     fn sin(f: f64) -> f64 {
         ...
-# fail;
+# die!();
     }
     fn cos(f: f64) -> f64 {
         ...
-# fail;
+# die!();
     }
     fn tan(f: f64) -> f64 {
         ...
-# fail;
+# die!();
     }
 }
 ~~~~~~~~
@@ -992,13 +992,13 @@ output slot type would normally be. For example:
 ~~~~
 fn my_err(s: &str) -> ! {
     log(info, s);
-    fail;
+    die!();
 }
 ~~~~
 
 We call such functions "diverging" because they never return a value to the
 caller. Every control path in a diverging function must end with a
-[`fail`](#fail-expressions) or a call to another diverging function on every
+`fail!()` or a call to another diverging function on every
 control path. The `!` annotation does *not* denote a type. Rather, the result
 type of a diverging function is a special type called $\bot$ ("bottom") that
 unifies with any type. Rust has no syntax for $\bot$.
@@ -1010,7 +1010,7 @@ were declared without the `!` annotation, the following code would not
 typecheck:
 
 ~~~~
-# fn my_err(s: &str) -> ! { fail }
+# fn my_err(s: &str) -> ! { die!() }
 
 fn f(i: int) -> int {
    if i == 42 {
@@ -2294,9 +2294,9 @@ enum List<X> { Nil, Cons(X, @List<X>) }
 let x: List<int> = Cons(10, @Cons(11, @Nil));
 
 match x {
-    Cons(_, @Nil) => fail ~"singleton list",
+    Cons(_, @Nil) => die!(~"singleton list"),
     Cons(*)       => return,
-    Nil           => fail ~"empty list"
+    Nil           => die!(~"empty list")
 }
 ~~~~
 
@@ -2333,7 +2333,7 @@ match x {
         return;
     }
     _ => {
-        fail;
+        die!();
     }
 }
 ~~~~
@@ -2421,23 +2421,10 @@ guard may refer to the variables bound within the pattern they follow.
 let message = match maybe_digit {
   Some(x) if x < 10 => process_digit(x),
   Some(x) => process_other(x),
-  None => fail
+  None => die!()
 };
 ~~~~
 
-
-### Fail expressions
-
-~~~~~~~~{.ebnf .gram}
-fail_expr : "fail" expr ? ;
-~~~~~~~~
-
-Evaluating a `fail` expression causes a task to enter the *failing* state. In
-the *failing* state, a task unwinds its stack, destroying all frames and
-running all destructors until it reaches its entry frame, at which point it
-halts execution in the *dead* state.
-
-
 ### Return expressions
 
 ~~~~~~~~{.ebnf .gram}
@@ -3157,7 +3144,7 @@ unblock and transition back to *running*.
 
 A task may transition to the *failing* state at any time, due being
 killed by some external event or internally, from the evaluation of a
-`fail` expression. Once *failing*, a task unwinds its stack and
+`fail!()` macro. Once *failing*, a task unwinds its stack and
 transitions to the *dead* state. Unwinding the stack of a task is done by
 the task itself, on its own control stack. If a value with a destructor is
 freed during unwinding, the code for the destructor is run, also on the task's
diff --git a/doc/tutorial-macros.md b/doc/tutorial-macros.md
index d1dd14a6d0a..4db584f2065 100644
--- a/doc/tutorial-macros.md
+++ b/doc/tutorial-macros.md
@@ -218,7 +218,7 @@ match x {
                 // complicated stuff goes here
                 return result + val;
             },
-            _ => fail ~"Didn't get good_2"
+            _ => die!(~"Didn't get good_2")
         }
     }
     _ => return 0 // default value
@@ -260,7 +260,7 @@ macro_rules! biased_match (
 biased_match!((x)       ~ (good_1(g1, val)) else { return 0 };
               binds g1, val )
 biased_match!((g1.body) ~ (good_2(result) )
-                  else { fail ~"Didn't get good_2" };
+                  else { die!(~"Didn't get good_2") };
               binds result )
 // complicated stuff goes here
 return result + val;
@@ -362,7 +362,7 @@ macro_rules! biased_match (
 # fn f(x: t1) -> uint {
 biased_match!(
     (x)       ~ (good_1(g1, val)) else { return 0 };
-    (g1.body) ~ (good_2(result) ) else { fail ~"Didn't get good_2" };
+    (g1.body) ~ (good_2(result) ) else { die!(~"Didn't get good_2") };
     binds val, result )
 // complicated stuff goes here
 return result + val;
diff --git a/doc/tutorial-tasks.md b/doc/tutorial-tasks.md
index 98ed6b86584..3434ef022da 100644
--- a/doc/tutorial-tasks.md
+++ b/doc/tutorial-tasks.md
@@ -13,7 +13,7 @@ cheaper to create than traditional threads, Rust can create hundreds of
 thousands of concurrent tasks on a typical 32-bit system.
 
 Tasks provide failure isolation and recovery. When an exception occurs in Rust
-code (as a result of an explicit call to `fail`, an assertion failure, or
+code (as a result of an explicit call to `fail!()`, an assertion failure, or
 another invalid operation), the runtime system destroys the entire
 task. Unlike in languages such as Java and C++, there is no way to `catch` an
 exception. Instead, tasks may monitor each other for failure.
@@ -296,9 +296,9 @@ let result = ports.foldl(0, |accum, port| *accum + port.recv() );
 
 # Handling task failure
 
-Rust has a built-in mechanism for raising exceptions. The `fail` construct
-(which can also be written with an error string as an argument: `fail
-~reason`) and the `assert` construct (which effectively calls `fail` if a
+Rust has a built-in mechanism for raising exceptions. The `fail!()` macro
+(which can also be written with an error string as an argument: `fail!(
+~reason)`) and the `assert` construct (which effectively calls `fail!()` if a
 boolean expression is false) are both ways to raise exceptions. When a task
 raises an exception the task unwinds its stack---running destructors and
 freeing memory along the way---and then exits. Unlike exceptions in C++,
@@ -313,7 +313,7 @@ of all tasks are intertwined: if one fails, so do all the others.
 # fn do_some_work() { loop { task::yield() } }
 # do task::try {
 // Create a child task that fails
-do spawn { fail }
+do spawn { die!() }
 
 // This will also fail because the task we spawned failed
 do_some_work();
@@ -337,7 +337,7 @@ let result: Result<int, ()> = do task::try {
     if some_condition() {
         calculate_result()
     } else {
-        fail ~"oops!";
+        die!(~"oops!");
     }
 };
 assert result.is_err();
@@ -354,7 +354,7 @@ an `Error` result.
 > ***Note:*** A failed task does not currently produce a useful error
 > value (`try` always returns `Err(())`). In the
 > future, it may be possible for tasks to intercept the value passed to
-> `fail`.
+> `fail!()`.
 
 TODO: Need discussion of `future_result` in order to make failure
 modes useful.
@@ -377,7 +377,7 @@ either task dies, it kills the other one.
 # do task::try {
 do task::spawn {
     do task::spawn {
-        fail;  // All three tasks will die.
+        die!();  // All three tasks will die.
     }
     sleep_forever();  // Will get woken up by force, then fail
 }
@@ -432,7 +432,7 @@ do task::spawn_supervised {
     // Intermediate task immediately exits
 }
 wait_for_a_while();
-fail;  // Will kill grandchild even if child has already exited
+die!();  // Will kill grandchild even if child has already exited
 # };
 ~~~
 
@@ -446,10 +446,10 @@ other at all, using `task::spawn_unlinked` for _isolated failure_.
 let (time1, time2) = (random(), random());
 do task::spawn_unlinked {
     sleep_for(time2);  // Won't get forced awake
-    fail;
+    die!();
 }
 sleep_for(time1);  // Won't get forced awake
-fail;
+die!();
 // It will take MAX(time1,time2) for the program to finish.
 # };
 ~~~
diff --git a/src/libcargo/cargo.rc b/src/libcargo/cargo.rc
index a1a026b9086..cb455852261 100644
--- a/src/libcargo/cargo.rc
+++ b/src/libcargo/cargo.rc
@@ -460,7 +460,7 @@ pub fn parse_source(name: ~str, j: &json::Json) -> @Source {
         json::Object(j) => {
             let mut url = match j.find(&~"url") {
                 Some(&json::String(u)) => copy u,
-                _ => fail ~"needed 'url' field in source"
+                _ => die!(~"needed 'url' field in source")
             };
             let method = match j.find(&~"method") {
                 Some(&json::String(u)) => copy u,
diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs
index 8b1a16a725a..2fd7d71a7fc 100644
--- a/src/libcore/dvec.rs
+++ b/src/libcore/dvec.rs
@@ -179,7 +179,7 @@ impl<A> DVec<A> {
             let mut data = cast::reinterpret_cast(&null::<()>());
             data <-> self.data;
             let data_ptr: *() = cast::reinterpret_cast(&data);
-            if data_ptr.is_null() { fail ~"Recursive use of dvec"; }
+            if data_ptr.is_null() { die!(~"Recursive use of dvec"); }
             self.data = move ~[move t];
             self.data.push_all_move(move data);
         }
diff --git a/src/libcore/hashmap.rs b/src/libcore/hashmap.rs
index 2cf7053246d..adb16a92905 100644
--- a/src/libcore/hashmap.rs
+++ b/src/libcore/hashmap.rs
@@ -386,7 +386,7 @@ pub mod linear {
         pure fn get(&self, k: &K) -> &self/V {
             match self.find(k) {
                 Some(v) => v,
-                None => fail fmt!("No entry found for key: %?", k),
+                None => die!(fmt!("No entry found for key: %?", k)),
             }
         }
     }
diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs
index 5f6ee3baf02..254e6010b1b 100644
--- a/src/libcore/pipes.rs
+++ b/src/libcore/pipes.rs
@@ -549,7 +549,7 @@ pub fn send<T,Tbuffer>(p: SendPacketBuffered<T,Tbuffer>, payload: T) -> bool {
             //unsafe { forget(p); }
             return true;
         }
-        Full => fail ~"duplicate send",
+        Full => die!(~"duplicate send"),
         Blocked => {
             debug!("waking up task for %?", p_);
             let old_task = swap_task(&mut p.header.blocked_task, ptr::null());
@@ -1020,7 +1020,7 @@ impl<T:Owned,Tbuffer:Owned> SendPacketBuffered<T,Tbuffer> {
             //forget(packet);
             header
           },
-          None => fail ~"packet already consumed"
+          None => die!(~"packet already consumed")
         }
     }
 
diff --git a/src/libcore/private/finally.rs b/src/libcore/private/finally.rs
index 6fd173f84aa..2c27b8ab3a2 100644
--- a/src/libcore/private/finally.rs
+++ b/src/libcore/private/finally.rs
@@ -71,7 +71,7 @@ fn test_fail() {
     let mut i = 0;
     do (|| {
         i = 10;
-        fail;
+        die!();
     }).finally {
         assert failing();
         assert i == 10;
@@ -95,4 +95,4 @@ fn test_compact() {
     fn but_always_run_this_function() { }
     do_some_fallible_work.finally(
         but_always_run_this_function);
-}
\ No newline at end of file
+}
diff --git a/src/libcore/private/global.rs b/src/libcore/private/global.rs
index eab3f8ee537..cc46c19c3d2 100644
--- a/src/libcore/private/global.rs
+++ b/src/libcore/private/global.rs
@@ -269,7 +269,7 @@ fn test_modify() {
                         Some(~shared_mutable_state(10))
                     }
                 }
-                _ => fail
+                _ => die!()
             }
         }
 
@@ -280,7 +280,7 @@ fn test_modify() {
                     assert *v == 10;
                     None
                 },
-                _ => fail
+                _ => die!()
             }
         }
 
@@ -291,7 +291,7 @@ fn test_modify() {
                         Some(~shared_mutable_state(10))
                     }
                 }
-                _ => fail
+                _ => die!()
             }
         }
     }
diff --git a/src/libcore/private/weak_task.rs b/src/libcore/private/weak_task.rs
index 7a299d6f11b..9d57cd5a466 100644
--- a/src/libcore/private/weak_task.rs
+++ b/src/libcore/private/weak_task.rs
@@ -112,7 +112,7 @@ fn run_weak_task_service(port: Port<ServiceMsg>) {
                         // nobody will receive this
                         shutdown_chan.send(());
                     }
-                    None => fail
+                    None => die!()
                 }
             }
             Shutdown => break
@@ -195,7 +195,7 @@ fn test_select_stream_and_oneshot() {
             do weaken_task |signal| {
                 match select2i(&port, &signal) {
                     Left(*) => (),
-                    Right(*) => fail
+                    Right(*) => die!()
                 }
             }
         }
diff --git a/src/libcore/repr.rs b/src/libcore/repr.rs
index 655a8754f01..a5c3afcc87f 100644
--- a/src/libcore/repr.rs
+++ b/src/libcore/repr.rs
@@ -594,7 +594,7 @@ impl ReprVisitor : TyVisitor {
     }
 
     // Type no longer exists, vestigial function.
-    fn visit_str(&self) -> bool { fail; }
+    fn visit_str(&self) -> bool { die!(); }
 
     fn visit_estr_box(&self) -> bool {
         do self.get::<@str> |s| {
@@ -616,7 +616,7 @@ impl ReprVisitor : TyVisitor {
 
     // Type no longer exists, vestigial function.
     fn visit_estr_fixed(&self, _n: uint, _sz: uint,
-                        _align: uint) -> bool { fail; }
+                        _align: uint) -> bool { die!(); }
 
     fn visit_box(&self, mtbl: uint, inner: *TyDesc) -> bool {
         self.writer.write_char('@');
@@ -652,7 +652,7 @@ impl ReprVisitor : TyVisitor {
     }
 
     // Type no longer exists, vestigial function.
-    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { fail; }
+    fn visit_vec(&self, _mtbl: uint, _inner: *TyDesc) -> bool { die!(); }
 
 
     fn visit_unboxed_vec(&self, mtbl: uint, inner: *TyDesc) -> bool {
@@ -859,7 +859,7 @@ impl ReprVisitor : TyVisitor {
     }
 
     // Type no longer exists, vestigial function.
-    fn visit_constr(&self, _inner: *TyDesc) -> bool { fail; }
+    fn visit_constr(&self, _inner: *TyDesc) -> bool { die!(); }
 
     fn visit_closure_ptr(&self, _ck: uint) -> bool { true }
 }
diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs
index a34956c87ba..d276f0c6ea9 100644
--- a/src/libcore/task/mod.rs
+++ b/src/libcore/task/mod.rs
@@ -733,7 +733,7 @@ fn test_spawn_linked_sup_fail_up() { // child fails; parent fails
         can_not_copy: None,
         .. b0
     };
-    do b1.spawn { fail; }
+    do b1.spawn { die!(); }
     po.recv(); // We should get punted awake
 }
 #[test] #[should_fail] #[ignore(cfg(windows))]
@@ -760,7 +760,7 @@ fn test_spawn_linked_sup_fail_down() { // parent fails; child fails
 fn test_spawn_linked_unsup_fail_up() { // child fails; parent fails
     let (po, _ch) = stream::<()>();
     // Default options are to spawn linked & unsupervised.
-    do spawn { fail; }
+    do spawn { die!(); }
     po.recv(); // We should get punted awake
 }
 #[test] #[should_fail] #[ignore(cfg(windows))]
diff --git a/src/libcore/task/spawn.rs b/src/libcore/task/spawn.rs
index e5fa0db63a1..ce95cdd0205 100644
--- a/src/libcore/task/spawn.rs
+++ b/src/libcore/task/spawn.rs
@@ -646,25 +646,25 @@ pub fn spawn_raw(opts: TaskOpts, f: fn~()) {
 
     fn new_task_in_sched(opts: SchedOpts) -> *rust_task {
         if opts.foreign_stack_size != None {
-            fail ~"foreign_stack_size scheduler option unimplemented";
+            die!(~"foreign_stack_size scheduler option unimplemented");
         }
 
         let num_threads = match opts.mode {
-          DefaultScheduler
-          | CurrentScheduler
-          | ExistingScheduler(*)
-          | PlatformThread => 0u, /* Won't be used */
-          SingleThreaded => 1u,
-          ThreadPerCore => unsafe { rt::rust_num_threads() },
-          ThreadPerTask => {
-            fail ~"ThreadPerTask scheduling mode unimplemented"
-          }
-          ManualThreads(threads) => {
-            if threads == 0u {
-                fail ~"can not create a scheduler with no threads";
+            DefaultScheduler
+            | CurrentScheduler
+            | ExistingScheduler(*)
+            | PlatformThread => 0u, /* Won't be used */
+            SingleThreaded => 1u,
+            ThreadPerCore => unsafe { rt::rust_num_threads() },
+            ThreadPerTask => {
+                die!(~"ThreadPerTask scheduling mode unimplemented")
+            }
+            ManualThreads(threads) => {
+                if threads == 0u {
+                    die!(~"can not create a scheduler with no threads");
+                }
+                threads
             }
-            threads
-          }
         };
 
         unsafe {
diff --git a/src/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc
index fd92b144b5d..c8083554c8b 100644
--- a/src/libfuzzer/fuzzer.rc
+++ b/src/libfuzzer/fuzzer.rc
@@ -84,9 +84,6 @@ pub fn common_exprs() -> ~[ast::expr] {
 
     ~[dse(ast::expr_break(option::None)),
      dse(ast::expr_again(option::None)),
-     dse(ast::expr_fail(option::None)),
-     dse(ast::expr_fail(option::Some(
-         @dse(ast::expr_lit(@dsl(ast::lit_str(@~"boo"))))))),
      dse(ast::expr_ret(option::None)),
      dse(ast::expr_lit(@dsl(ast::lit_nil))),
      dse(ast::expr_lit(@dsl(ast::lit_bool(false)))),
@@ -117,11 +114,10 @@ pub pure fn safe_to_use_expr(e: ast::expr, tm: test_mode) -> bool {
           ast::expr_binary(*) | ast::expr_assign(*) |
           ast::expr_assign_op(*) => { false }
 
-          ast::expr_fail(option::None) |
           ast::expr_ret(option::None) => { false }
 
           // https://github.com/mozilla/rust/issues/953
-          ast::expr_fail(option::Some(_)) => { false }
+          //ast::expr_fail(option::Some(_)) => { false }
 
           // https://github.com/mozilla/rust/issues/928
           //ast::expr_cast(_, _) { false }
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 0f61d12d7c8..33879237ffb 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -886,7 +886,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: writer::Encoder,
                         encode_info_for_item(ecx, ebml_w, i,
                                              index, *pt);
                     }
-                    _ => fail ~"bad item"
+                    _ => die!(~"bad item")
                 }
             }
         },
@@ -901,7 +901,7 @@ fn encode_info_for_items(ecx: @encode_ctxt, ebml_w: writer::Encoder,
                                                      abi);
                     }
                     // case for separate item and foreign-item tables
-                    _ => fail ~"bad foreign item"
+                    _ => die!(~"bad foreign item")
                 }
             }
         },
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 5d57f680200..47fd0b526a6 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -610,7 +610,7 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) {
       expr_tup(*) | expr_log(*) | expr_binary(*) |
       expr_assert(*) | expr_addr_of(*) | expr_copy(*) |
       expr_loop_body(*) | expr_do_body(*) | expr_cast(*) |
-      expr_unary(*) | expr_fail(*) |
+      expr_unary(*) |
       expr_break(_) | expr_again(_) | expr_lit(_) | expr_ret(*) |
       expr_block(*) | expr_assign(*) |
       expr_swap(*) | expr_assign_op(*) | expr_mac(*) | expr_struct(*) |
@@ -1191,7 +1191,7 @@ impl Liveness {
             self.propagate_through_expr(e, ln)
           }
 
-          expr_ret(o_e) | expr_fail(o_e) => {
+          expr_ret(o_e) => {
             // ignore succ and subst exit_ln:
             self.propagate_through_opt_expr(o_e, self.s.exit_ln)
           }
@@ -1608,7 +1608,7 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
       expr_log(*) | expr_binary(*) |
       expr_assert(*) | expr_copy(*) |
       expr_loop_body(*) | expr_do_body(*) |
-      expr_cast(*) | expr_unary(*) | expr_fail(*) |
+      expr_cast(*) | expr_unary(*) |
       expr_ret(*) | expr_break(*) | expr_again(*) | expr_lit(_) |
       expr_block(*) | expr_swap(*) | expr_mac(*) | expr_addr_of(*) |
       expr_struct(*) | expr_repeat(*) | expr_paren(*) => {
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 625b9889aad..85cae4a0e67 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -387,7 +387,7 @@ pub impl &mem_categorization_ctxt {
           ast::expr_assert(*) | ast::expr_ret(*) |
           ast::expr_loop_body(*) | ast::expr_do_body(*) |
           ast::expr_unary(*) | ast::expr_method_call(*) |
-          ast::expr_copy(*) | ast::expr_cast(*) | ast::expr_fail(*) |
+          ast::expr_copy(*) | ast::expr_cast(*) |
           ast::expr_vstore(*) | ast::expr_vec(*) | ast::expr_tup(*) |
           ast::expr_if(*) | ast::expr_log(*) |
           ast::expr_binary(*) | ast::expr_while(*) |
diff --git a/src/librustc/middle/moves.rs b/src/librustc/middle/moves.rs
index 81b3761451c..30812a67a7b 100644
--- a/src/librustc/middle/moves.rs
+++ b/src/librustc/middle/moves.rs
@@ -573,7 +573,6 @@ impl VisitContext {
                 self.consume_block(blk, visitor);
             }
 
-            expr_fail(ref opt_expr) |
             expr_ret(ref opt_expr) => {
                 for opt_expr.each |expr| {
                     self.consume_expr(*expr, visitor);
@@ -812,4 +811,4 @@ impl VisitContext {
             })
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs
index 1bb74f265c3..75a627a4422 100644
--- a/src/librustc/middle/trans/expr.rs
+++ b/src/librustc/middle/trans/expr.rs
@@ -468,9 +468,6 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
         ast::expr_ret(ex) => {
             return controlflow::trans_ret(bcx, ex);
         }
-        ast::expr_fail(why) => {
-            return controlflow::trans_fail_expr(bcx, Some(expr.span), why);
-        }
         ast::expr_log(_, lvl, a) => {
             return controlflow::trans_log(expr, lvl, bcx, a);
         }
diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs
index d1621233f5d..5a5644fefb9 100644
--- a/src/librustc/middle/trans/meth.rs
+++ b/src/librustc/middle/trans/meth.rs
@@ -265,7 +265,8 @@ pub fn trans_method_callee(bcx: block,
                                mentry.explicit_self)
         }
         typeck::method_self(*) | typeck::method_super(*) => {
-            fail ~"method_self or method_super should have been handled above"
+            die!(~"method_self or method_super should have been handled \
+                above")
         }
     }
 }
diff --git a/src/librustc/middle/trans/type_use.rs b/src/librustc/middle/trans/type_use.rs
index 7484967e9e5..baf84436eab 100644
--- a/src/librustc/middle/trans/type_use.rs
+++ b/src/librustc/middle/trans/type_use.rs
@@ -340,7 +340,7 @@ pub fn mark_for_expr(cx: ctx, e: @expr) {
       }
       expr_paren(e) => mark_for_expr(cx, e),
       expr_match(*) | expr_block(_) | expr_if(*) |
-      expr_while(*) | expr_fail(_) | expr_break(_) | expr_again(_) |
+      expr_while(*) | expr_break(_) | expr_again(_) |
       expr_unary(_, _) | expr_lit(_) | expr_assert(_) |
       expr_mac(_) | expr_addr_of(_, _) |
       expr_ret(_) | expr_loop(_, _) |
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index e0ac6fa7594..1fd082bb65c 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -2860,7 +2860,7 @@ pub pure fn ty_vstore(ty: t) -> vstore {
     match get(ty).sty {
         ty_evec(_, vstore) => vstore,
         ty_estr(vstore) => vstore,
-        ref s => fail fmt!("ty_vstore() called on invalid sty: %?", s)
+        ref s => die!(fmt!("ty_vstore() called on invalid sty: %?", s))
     }
 }
 
@@ -2869,7 +2869,8 @@ pub fn ty_region(ty: t) -> Region {
       ty_rptr(r, _) => r,
       ty_evec(_, vstore_slice(r)) => r,
       ty_estr(vstore_slice(r)) => r,
-      ref s => fail fmt!("ty_region() invoked on in appropriate ty: %?", (*s))
+      ref s => die!(fmt!("ty_region() invoked on in appropriate ty: %?",
+          (*s)))
     }
 }
 
@@ -3205,7 +3206,6 @@ pub fn expr_kind(tcx: ctxt,
         ast::expr_again(*) |
         ast::expr_ret(*) |
         ast::expr_log(*) |
-        ast::expr_fail(*) |
         ast::expr_assert(*) |
         ast::expr_while(*) |
         ast::expr_loop(*) |
diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs
index 51650804c50..7f82e916d74 100644
--- a/src/librustc/middle/typeck/check/method.rs
+++ b/src/librustc/middle/typeck/check/method.rs
@@ -1233,7 +1233,7 @@ pub impl LookupContext {
         let span = if did.crate == ast::local_crate {
             match self.tcx().items.find(did.node) {
               Some(ast_map::node_method(m, _, _)) => m.span,
-              _ => fail fmt!("report_static_candidate: bad item %?", did)
+              _ => die!(fmt!("report_static_candidate: bad item %?", did))
             }
         } else {
             self.expr.span
diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index b71bee74f9c..5eb33629370 100644
--- a/src/librustc/middle/typeck/check/mod.rs
+++ b/src/librustc/middle/typeck/check/mod.rs
@@ -2087,17 +2087,6 @@ pub fn check_expr_with_unifier(fcx: @fn_ctxt,
         instantiate_path(fcx, pth, tpt, expr.span, expr.id, region_lb);
       }
       ast::expr_mac(_) => tcx.sess.bug(~"unexpanded macro"),
-      ast::expr_fail(expr_opt) => {
-        bot = true;
-        match expr_opt {
-          None => {/* do nothing */ }
-          Some(e) => {
-            check_expr_has_type(
-                fcx, e, ty::mk_estr(tcx, ty::vstore_uniq));
-          }
-        }
-        fcx.write_bot(id);
-      }
       ast::expr_break(_) => { fcx.write_bot(id); bot = true; }
       ast::expr_again(_) => { fcx.write_bot(id); bot = true; }
       ast::expr_ret(expr_opt) => {
diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs
index ae8574f8d1e..89e156f2741 100644
--- a/src/librustc/middle/typeck/check/regionck.rs
+++ b/src/librustc/middle/typeck/check/regionck.rs
@@ -689,7 +689,6 @@ pub mod guarantor {
             ast::expr_again(*) |
             ast::expr_ret(*) |
             ast::expr_log(*) |
-            ast::expr_fail(*) |
             ast::expr_assert(*) |
             ast::expr_while(*) |
             ast::expr_loop(*) |
diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs
index 382695e40f7..d4789ace703 100644
--- a/src/librustdoc/attr_pass.rs
+++ b/src/librustdoc/attr_pass.rs
@@ -119,7 +119,7 @@ fn parse_item_attrs<T:Owned>(
         let attrs = match ctxt.ast_map.get(id) {
           ast_map::node_item(item, _) => copy item.attrs,
           ast_map::node_foreign_item(item, _, _) => copy item.attrs,
-          _ => fail ~"parse_item_attrs: not an item"
+          _ => die!(~"parse_item_attrs: not an item")
         };
         parse_attrs(attrs)
     }
@@ -183,9 +183,9 @@ fn fold_enum(
                                 copy ast_variant.node.attrs)
                         }
                         _ => {
-                            fail fmt!("Enum variant %s has id that's \
+                            die!(fmt!("Enum variant %s has id that's \
                                        not bound to an enum item",
-                                      variant.name)
+                                      variant.name))
                         }
                     }
                 }
diff --git a/src/librustdoc/demo.rs b/src/librustdoc/demo.rs
index d069fc14207..ff6b745612d 100644
--- a/src/librustdoc/demo.rs
+++ b/src/librustdoc/demo.rs
@@ -192,6 +192,6 @@ impl OmNomNomy: TheShunnedHouse {
     }
 
     fn construct(&self) -> bool {
-        fail;
+        die!();
     }
 }
diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs
index 417171e6773..880e7ea1435 100644
--- a/src/librustdoc/tystr_pass.rs
+++ b/src/librustdoc/tystr_pass.rs
@@ -113,7 +113,7 @@ fn fold_const(
                     }, _) => {
                         pprust::ty_to_str(ty, extract::interner())
                     }
-                    _ => fail ~"fold_const: id not bound to a const item"
+                    _ => die!(~"fold_const: id not bound to a const item")
                 }
             }}),
         .. doc
@@ -150,7 +150,7 @@ fn fold_enum(
                             pprust::variant_to_str(
                                 ast_variant, extract::interner())
                         }
-                        _ => fail ~"enum variant not bound to an enum item"
+                        _ => die!(~"enum variant not bound to an enum item")
                     }
                 }
             };
@@ -282,7 +282,7 @@ fn fold_impl(
                      Some(pprust::ty_to_str(
                          self_ty, extract::interner())))
                 }
-                _ => fail ~"expected impl"
+                _ => die!(~"expected impl")
             }
         }
     };
@@ -345,7 +345,7 @@ fn fold_type(
                                               extract::interner())
                         ))
                     }
-                    _ => fail ~"expected type"
+                    _ => die!(~"expected type")
                 }
             }
         },
@@ -375,7 +375,7 @@ fn fold_struct(
                         Some(pprust::item_to_str(item,
                                                  extract::interner()))
                     }
-                    _ => fail ~"not an item"
+                    _ => die!(~"not an item")
                 }
             }
         },
diff --git a/src/libstd/bigint.rs b/src/libstd/bigint.rs
index 2ccf3477141..0104e72764f 100644
--- a/src/libstd/bigint.rs
+++ b/src/libstd/bigint.rs
@@ -245,7 +245,7 @@ impl BigUint : Modulo<BigUint, BigUint> {
 }
 
 impl BigUint : Neg<BigUint> {
-    pure fn neg(&self) -> BigUint { fail }
+    pure fn neg(&self) -> BigUint { die!() }
 }
 
 impl BigUint : IntConvertible {
diff --git a/src/libstd/net_tcp.rs b/src/libstd/net_tcp.rs
index 91fdd07f65f..b86286a198d 100644
--- a/src/libstd/net_tcp.rs
+++ b/src/libstd/net_tcp.rs
@@ -940,7 +940,7 @@ impl TcpSocketBuf: io::Reader {
               } else {
                   debug!("ERROR sock_buf as io::reader.read err %? %?",
                          err_data.err_name, err_data.err_msg);
-                  fail
+                  die!()
               }
           }
           else {
diff --git a/src/libstd/test.rs b/src/libstd/test.rs
index c287872996c..5a2693a42c1 100644
--- a/src/libstd/test.rs
+++ b/src/libstd/test.rs
@@ -446,7 +446,7 @@ mod tests {
 
     #[test]
     pub fn do_not_run_ignored_tests() {
-        fn f() { fail; }
+        fn f() { die!(); }
         let desc = TestDesc {
             name: ~"whatever",
             testfn: f,
@@ -479,7 +479,7 @@ mod tests {
     #[test]
     #[ignore(cfg(windows))]
     pub fn test_should_fail() {
-        fn f() { fail; }
+        fn f() { die!(); }
         let desc = TestDesc {
             name: ~"whatever",
             testfn: f,
diff --git a/src/libstd/uv_global_loop.rs b/src/libstd/uv_global_loop.rs
index 8ae3e24abee..736954f6b22 100644
--- a/src/libstd/uv_global_loop.rs
+++ b/src/libstd/uv_global_loop.rs
@@ -185,14 +185,12 @@ mod test {
                         let start_status = ll::timer_start(timer_ptr,
                                                            simple_timer_cb,
                                                            1u, 0u);
-                        if(start_status == 0i32) {
-                        }
-                        else {
-                            fail ~"failure on ll::timer_start()";
+                        if(start_status != 0i32) {
+                            die!(~"failure on ll::timer_start()");
                         }
                     }
                     else {
-                        fail ~"failure on ll::timer_init()";
+                        die!(~"failure on ll::timer_init()");
                     }
                 }
             };
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 393020b6643..a651090cf64 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -686,7 +686,7 @@ pub enum expr_ {
     expr_cast(@expr, @Ty),
     expr_if(@expr, blk, Option<@expr>),
     expr_while(@expr, blk),
-    /* Conditionless loop (can be exited with break, cont, ret, or fail)
+    /* Conditionless loop (can be exited with break, cont, or ret)
        Same semantics as while(true) { body }, but typestate knows that the
        (implicit) condition is always true. */
     expr_loop(blk, Option<ident>),
@@ -712,7 +712,6 @@ pub enum expr_ {
     expr_index(@expr, @expr),
     expr_path(@path),
     expr_addr_of(mutability, @expr),
-    expr_fail(Option<@expr>),
     expr_break(Option<ident>),
     expr_again(Option<ident>),
     expr_ret(Option<@expr>),
diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs
index 4dddb66995b..622db9400be 100644
--- a/src/libsyntax/ext/auto_encode.rs
+++ b/src/libsyntax/ext/auto_encode.rs
@@ -1025,7 +1025,7 @@ fn mk_enum_deser_variant_nary(
 }
 
 fn mk_enum_deser_body(
-    cx: ext_ctxt,
+    ext_cx: ext_ctxt,
     span: span,
     name: ast::ident,
     variants: ~[ast::variant]
@@ -1035,11 +1035,11 @@ fn mk_enum_deser_body(
             ast::tuple_variant_kind(args) => {
                 if args.is_empty() {
                     // for a nullary variant v, do "v"
-                    cx.expr_path(span, ~[variant.node.name])
+                    ext_cx.expr_path(span, ~[variant.node.name])
                 } else {
                     // for an n-ary variant v, do "v(a_1, ..., a_n)"
                     mk_enum_deser_variant_nary(
-                        cx,
+                        ext_cx,
                         span,
                         variant.node.name,
                         args
@@ -1053,94 +1053,99 @@ fn mk_enum_deser_body(
         };
 
         let pat = @ast::pat {
-            id: cx.next_id(),
-            node: ast::pat_lit(cx.lit_uint(span, v_idx)),
+            id: ext_cx.next_id(),
+            node: ast::pat_lit(ext_cx.lit_uint(span, v_idx)),
             span: span,
         };
 
         ast::arm {
             pats: ~[pat],
             guard: None,
-            body: cx.expr_blk(body),
+            body: ext_cx.expr_blk(body),
         }
     };
 
+    let quoted_expr = quote_expr!(
+      ::core::sys::begin_unwind(~"explicit failure", ~"empty", 1);
+    ).node;
+
     let impossible_case = ast::arm {
         pats: ~[@ast::pat {
-            id: cx.next_id(),
+            id: ext_cx.next_id(),
             node: ast::pat_wild,
             span: span,
         }],
         guard: None,
 
         // FIXME(#3198): proper error message
-        body: cx.expr_blk(cx.expr(span, ast::expr_fail(None))),
+        body: ext_cx.expr_blk(ext_cx.expr(span, quoted_expr)),
     };
 
     arms.push(impossible_case);
 
     // ast for `|i| { match i { $(arms) } }`
-    let expr_lambda = cx.expr(
+    let expr_lambda = ext_cx.expr(
         span,
         ast::expr_fn_block(
             ast::fn_decl {
                 inputs: ~[ast::arg {
-                    mode: ast::infer(cx.next_id()),
+                    mode: ast::infer(ext_cx.next_id()),
                     is_mutbl: false,
                     ty: @ast::Ty {
-                        id: cx.next_id(),
+                        id: ext_cx.next_id(),
                         node: ast::ty_infer,
                         span: span
                     },
                     pat: @ast::pat {
-                        id: cx.next_id(),
+                        id: ext_cx.next_id(),
                         node: ast::pat_ident(
                             ast::bind_by_copy,
-                            ast_util::ident_to_path(span, cx.ident_of(~"i")),
+                            ast_util::ident_to_path(span,
+                                ext_cx.ident_of(~"i")),
                             None),
                         span: span,
                     },
-                    id: cx.next_id(),
+                    id: ext_cx.next_id(),
                 }],
                 output: @ast::Ty {
-                    id: cx.next_id(),
+                    id: ext_cx.next_id(),
                     node: ast::ty_infer,
                     span: span,
                 },
                 cf: ast::return_val,
             },
-            cx.expr_blk(
-                cx.expr(
+            ext_cx.expr_blk(
+                ext_cx.expr(
                     span,
-                    ast::expr_match(cx.expr_var(span, ~"i"), arms)
+                    ast::expr_match(ext_cx.expr_var(span, ~"i"), arms)
                 )
             )
         )
     );
 
     // ast for `__d.read_enum_variant($(expr_lambda))`
-    let expr_lambda = cx.lambda_expr(
-        cx.expr_call(
+    let expr_lambda = ext_cx.lambda_expr(
+        ext_cx.expr_call(
             span,
-            cx.expr_field(
+            ext_cx.expr_field(
                 span,
-                cx.expr_var(span, ~"__d"),
-                cx.ident_of(~"read_enum_variant")
+                ext_cx.expr_var(span, ~"__d"),
+                ext_cx.ident_of(~"read_enum_variant")
             ),
             ~[expr_lambda]
         )
     );
 
     // ast for `__d.read_enum($(e_name), $(expr_lambda))`
-    cx.expr_call(
+    ext_cx.expr_call(
         span,
-        cx.expr_field(
+        ext_cx.expr_field(
             span,
-            cx.expr_var(span, ~"__d"),
-            cx.ident_of(~"read_enum")
+            ext_cx.expr_var(span, ~"__d"),
+            ext_cx.ident_of(~"read_enum")
         ),
         ~[
-            cx.lit_str(span, @cx.str_of(name)),
+            ext_cx.lit_str(span, @ext_cx.str_of(name)),
             expr_lambda
         ]
     )
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index be768650ef7..1d9c87f4e95 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -296,6 +296,15 @@ pub fn core_macros() -> ~str {
         )
     )
 
+    macro_rules! fail(
+        ($msg: expr) => (
+            ::core::sys::begin_unwind($msg, file!().to_owned(), line!())
+        );
+        () => (
+            die!(~\"explicit failure\")
+        )
+    )
+
     macro_rules! fail_unless(
         ($cond:expr) => {
             if !$cond {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 5c80a6664de..cfa8a3c1153 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -495,7 +495,6 @@ pub fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
             expr_index(fld.fold_expr(el), fld.fold_expr(er))
           }
           expr_path(pth) => expr_path(fld.fold_path(pth)),
-          expr_fail(e) => expr_fail(option::map(&e, |x| fld.fold_expr(*x))),
           expr_break(opt_ident) =>
             expr_break(option::map(&opt_ident, |x| fld.fold_ident(*x))),
           expr_again(opt_ident) =>
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 64692522286..06f86f134a6 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -20,7 +20,7 @@ use ast::{decl_local, default_blk, deref, div, enum_def, enum_variant_kind};
 use ast::{expl, expr, expr_, expr_addr_of, expr_match, expr_again};
 use ast::{expr_assert, expr_assign, expr_assign_op, expr_binary, expr_block};
 use ast::{expr_break, expr_call, expr_cast, expr_copy, expr_do_body};
-use ast::{expr_fail, expr_field, expr_fn, expr_fn_block, expr_if, expr_index};
+use ast::{expr_field, expr_fn, expr_fn_block, expr_if, expr_index};
 use ast::{expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac};
 use ast::{expr_method_call, expr_paren, expr_path, expr_rec, expr_repeat};
 use ast::{expr_ret, expr_swap, expr_struct, expr_tup, expr_unary};
@@ -1034,12 +1034,6 @@ pub impl Parser {
                 }
             }
             hi = self.span.hi;
-        } else if self.eat_keyword(~"fail") {
-            if can_begin_expr(self.token) {
-                let e = self.parse_expr();
-                hi = e.span.hi;
-                ex = expr_fail(Some(e));
-            } else { ex = expr_fail(None); }
         } else if self.eat_keyword(~"log") {
             self.expect(token::LPAREN);
             let lvl = self.parse_expr();
diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs
index bcf4281132d..843b0edcfc9 100644
--- a/src/libsyntax/parse/token.rs
+++ b/src/libsyntax/parse/token.rs
@@ -487,7 +487,7 @@ pub fn strict_keyword_table() -> HashMap<~str, ()> {
         ~"const", ~"copy",
         ~"do", ~"drop",
         ~"else", ~"enum", ~"extern",
-        ~"fail", ~"false", ~"fn", ~"for",
+        ~"false", ~"fn", ~"for",
         ~"if", ~"impl",
         ~"let", ~"log", ~"loop",
         ~"match", ~"mod", ~"move", ~"mut",
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 1b5c93984ee..527b036a46c 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -1393,13 +1393,6 @@ pub fn print_expr(s: ps, &&expr: @ast::expr) {
         word(s.s, ~"]");
       }
       ast::expr_path(path) => print_path(s, path, true),
-      ast::expr_fail(maybe_fail_val) => {
-        word(s.s, ~"fail");
-        match maybe_fail_val {
-          Some(expr) => { word(s.s, ~" "); print_expr(s, expr); }
-          _ => ()
-        }
-      }
       ast::expr_break(opt_ident) => {
         word(s.s, ~"break");
         space(s.s);
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index a174ea47740..eea1a6906e4 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -485,7 +485,6 @@ pub fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
         (v.visit_expr)(b, e, v);
       }
       expr_path(p) => visit_path(p, e, v),
-      expr_fail(eo) => visit_expr_opt(eo, e, v),
       expr_break(_) => (),
       expr_again(_) => (),
       expr_ret(eo) => visit_expr_opt(eo, e, v),
diff --git a/src/test/auxiliary/issue_2723_a.rs b/src/test/auxiliary/issue_2723_a.rs
index 5afb2161b41..ef74b61f93a 100644
--- a/src/test/auxiliary/issue_2723_a.rs
+++ b/src/test/auxiliary/issue_2723_a.rs
@@ -9,5 +9,5 @@
 // except according to those terms.
 
 pub unsafe fn f(xs: ~[int]) {
-    xs.map(|_x| { unsafe fn q() { fail; } });
+    xs.map(|_x| { unsafe fn q() { die!(); } });
 }
diff --git a/src/test/bench/shootout-chameneos-redux.rs b/src/test/bench/shootout-chameneos-redux.rs
index 740a2754e24..ad248a4aa29 100644
--- a/src/test/bench/shootout-chameneos-redux.rs
+++ b/src/test/bench/shootout-chameneos-redux.rs
@@ -63,7 +63,7 @@ fn show_digit(nn: uint) -> ~str {
         7 => {~"seven"}
         8 => {~"eight"}
         9 => {~"nine"}
-        _ => {fail ~"expected digits from 0 to 9..."}
+        _ => {die!(~"expected digits from 0 to 9...")}
     }
 }
 
diff --git a/src/test/bench/shootout-pfib.rs b/src/test/bench/shootout-pfib.rs
index c146b6ac371..06b46eab759 100644
--- a/src/test/bench/shootout-pfib.rs
+++ b/src/test/bench/shootout-pfib.rs
@@ -68,7 +68,7 @@ fn parse_opts(argv: ~[~str]) -> Config {
       Ok(ref m) => {
           return Config {stress: getopts::opt_present(m, ~"stress")}
       }
-      Err(_) => { fail; }
+      Err(_) => { die!(); }
     }
 }
 
diff --git a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
index 358917de85f..94067700270 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
@@ -2,7 +2,7 @@ fn a() -> &[int] {
     let vec = [1, 2, 3, 4];
     let tail = match vec { //~ ERROR illegal borrow
         [_a, ..tail] => tail,
-        _ => fail ~"foo"
+        _ => die!(~"foo")
     };
     move tail
 }
diff --git a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
index 50feff707ad..0a200e736ba 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-nesting.rs
@@ -4,7 +4,7 @@ fn a() {
         [~ref _a] => {
             vec[0] = ~4; //~ ERROR prohibited due to outstanding loan
         }
-        _ => fail ~"foo"
+        _ => die!(~"foo")
     }
 }
 
diff --git a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
index 6477fd9fb2c..64bb571b2dc 100644
--- a/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
+++ b/src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
@@ -2,7 +2,7 @@ fn a() -> &int {
     let vec = [1, 2, 3, 4];
     let tail = match vec { //~ ERROR illegal borrow
         [_a, ..tail] => &tail[0],
-        _ => fail ~"foo"
+        _ => die!(~"foo")
     };
     move tail
 }
diff --git a/src/test/compile-fail/issue-2151.rs b/src/test/compile-fail/issue-2151.rs
index f95452fa048..ef72f7245ac 100644
--- a/src/test/compile-fail/issue-2151.rs
+++ b/src/test/compile-fail/issue-2151.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 fn main() {
-    for vec::each(fail) |i| {
+    for vec::each(die!()) |i| {
         log (debug, i * 2);
         //~^ ERROR the type of this value must be known
    };
-}
\ No newline at end of file
+}
diff --git a/src/test/compile-fail/moves-based-on-type-exprs.rs b/src/test/compile-fail/moves-based-on-type-exprs.rs
index 07fe8318836..be842a4cdd7 100644
--- a/src/test/compile-fail/moves-based-on-type-exprs.rs
+++ b/src/test/compile-fail/moves-based-on-type-exprs.rs
@@ -2,7 +2,7 @@
 // they occur as part of various kinds of expressions.
 
 struct Foo<A> { f: A }
-fn guard(_s: ~str) -> bool {fail}
+fn guard(_s: ~str) -> bool {die!()}
 fn touch<A>(_a: &A) {}
 
 fn f10() {
@@ -92,4 +92,4 @@ fn f120() {
     touch(&x[1]);
 }
 
-fn main() {}
\ No newline at end of file
+fn main() {}
diff --git a/src/test/run-fail/fail-arg.rs b/src/test/run-fail/fail-arg.rs
index 62d3c824223..4ead0db2d42 100644
--- a/src/test/run-fail/fail-arg.rs
+++ b/src/test/run-fail/fail-arg.rs
@@ -11,4 +11,4 @@
 // error-pattern:woe
 fn f(a: int) { log(debug, a); }
 
-fn main() { f(fail ~"woe"); }
+fn main() { f(die!(~"woe")); }
diff --git a/src/test/run-fail/fail-parens.rs b/src/test/run-fail/fail-parens.rs
index 20ad9b00284..144a36bd730 100644
--- a/src/test/run-fail/fail-parens.rs
+++ b/src/test/run-fail/fail-parens.rs
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Fail statements without arguments need to be disambiguated in
+// Fail macros without arguments need to be disambiguated in
 // certain positions
 // error-pattern:oops
 
 fn bigfail() {
-    while (fail ~"oops") { if (fail) {
-        match (fail) { () => {
+    while (die!(~"oops")) { if (die!()) {
+        match (die!()) { () => {
         }
                      }
     }};
diff --git a/src/test/run-fail/issue-1459.rs b/src/test/run-fail/issue-1459.rs
index 3480d5e7c71..bb97e5b2b6a 100644
--- a/src/test/run-fail/issue-1459.rs
+++ b/src/test/run-fail/issue-1459.rs
@@ -10,5 +10,5 @@
 
 // error-pattern:roflcopter
 fn main() {
-    log (fail ~"roflcopter", 2);
+    log (die!(~"roflcopter"), 2);
 }
diff --git a/src/test/run-fail/issue-2444.rs b/src/test/run-fail/issue-2444.rs
index 9172364a2f9..a4c329a41fc 100644
--- a/src/test/run-fail/issue-2444.rs
+++ b/src/test/run-fail/issue-2444.rs
@@ -15,7 +15,7 @@ use std::arc;
 
 enum e<T> { e(arc::ARC<T>) }
 
-fn foo() -> e<int> {fail;}
+fn foo() -> e<int> {die!();}
 
 fn main() {
    let f = foo();
diff --git a/src/test/run-fail/issue-948.rs b/src/test/run-fail/issue-948.rs
index 7a41eb0ca50..ddb3eecdbf1 100644
--- a/src/test/run-fail/issue-948.rs
+++ b/src/test/run-fail/issue-948.rs
@@ -14,5 +14,5 @@ struct Point { x: int, y: int }
 
 fn main() {
     let origin = Point {x: 0, y: 0};
-    let f: Point = Point {x: (fail ~"beep boop"),.. origin};
+    let f: Point = Point {x: (die!(~"beep boop")),.. origin};
 }
diff --git a/src/test/run-fail/task-comm-recv-block.rs b/src/test/run-fail/task-comm-recv-block.rs
index fc108a4fbdd..0b36977d9b5 100644
--- a/src/test/run-fail/task-comm-recv-block.rs
+++ b/src/test/run-fail/task-comm-recv-block.rs
@@ -21,5 +21,5 @@ fn main() {
     // We shouldn't be able to get past this recv since there's no
     // message available
     let i: int = po.recv();
-    fail ~"badfail";
+    die!(~"badfail");
 }
diff --git a/src/test/run-fail/unique-fail.rs b/src/test/run-fail/unique-fail.rs
index e66688dadbe..0cb37dfd260 100644
--- a/src/test/run-fail/unique-fail.rs
+++ b/src/test/run-fail/unique-fail.rs
@@ -9,4 +9,4 @@
 // except according to those terms.
 
 // error-pattern: fail
-fn main() { ~fail; }
+fn main() { ~die!(); }
diff --git a/src/test/run-pass/region-dependent-addr-of.rs b/src/test/run-pass/region-dependent-addr-of.rs
index 6765c1a11ae..133904d34e1 100644
--- a/src/test/run-pass/region-dependent-addr-of.rs
+++ b/src/test/run-pass/region-dependent-addr-of.rs
@@ -54,21 +54,21 @@ fn get_v5(a: &v/A, i: uint) -> &v/int {
 fn get_v6_a(a: &v/A, i: uint) -> &v/int {
     match a.value.v6 {
         Some(ref v) => &v.f,
-        None => fail
+        None => die!()
     }
 }
 
 fn get_v6_b(a: &v/A, i: uint) -> &v/int {
     match *a {
         A { value: B { v6: Some(ref v), _ } } => &v.f,
-        _ => fail
+        _ => die!()
     }
 }
 
 fn get_v6_c(a: &v/A, i: uint) -> &v/int {
     match a {
         &A { value: B { v6: Some(ref v), _ } } => &v.f,
-        _ => fail
+        _ => die!()
     }
 }