about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Desaulniers <ndesaulniers@mozilla.com>2013-01-31 18:24:09 -0800
committerNick Desaulniers <ndesaulniers@mozilla.com>2013-02-01 00:15:42 -0800
commit7868b6bf550dcb1b74f25178bcac73d6ec767993 (patch)
treeb9449845e6244b4e8a47d8986dd5c5823f698ace
parent6fb4239bb361a927582a8ffd53a2ae649d810fdf (diff)
Remove fail keyword from lexer & parser and clean up remaining calls to
fail

Fix merge conflicts - Issue 4524
-rw-r--r--doc/lib/codemirror-rust.js2
-rw-r--r--doc/rust.md37
-rw-r--r--doc/tutorial-macros.md6
-rw-r--r--doc/tutorial-tasks.md22
-rw-r--r--src/libcore/pipes.rs2
-rw-r--r--src/libcore/private/finally.rs4
-rw-r--r--src/libcore/private/global.rs6
-rw-r--r--src/libcore/private/weak_task.rs4
-rw-r--r--src/libcore/repr.rs8
-rw-r--r--src/libfuzzer/fuzzer.rc6
-rw-r--r--src/librustc/middle/liveness.rs6
-rw-r--r--src/librustc/middle/mem_categorization.rs2
-rw-r--r--src/librustc/middle/moves.rs3
-rw-r--r--src/librustc/middle/trans/expr.rs3
-rw-r--r--src/librustc/middle/trans/type_use.rs2
-rw-r--r--src/librustc/middle/ty.rs3
-rw-r--r--src/librustc/middle/typeck/check/mod.rs11
-rw-r--r--src/librustc/middle/typeck/check/regionck.rs1
-rw-r--r--src/libsyntax/ast.rs3
-rw-r--r--src/libsyntax/ext/auto_encode.rs61
-rw-r--r--src/libsyntax/ext/expand.rs9
-rw-r--r--src/libsyntax/fold.rs1
-rw-r--r--src/libsyntax/parse/parser.rs8
-rw-r--r--src/libsyntax/parse/token.rs2
-rw-r--r--src/libsyntax/print/pprust.rs7
-rw-r--r--src/libsyntax/visit.rs1
-rw-r--r--src/test/bench/shootout-chameneos-redux.rs2
-rw-r--r--src/test/compile-fail/borrowck-vec-pattern-nesting.rs2
-rw-r--r--src/test/compile-fail/issue-2151.rs4
-rw-r--r--src/test/compile-fail/moves-based-on-type-exprs.rs4
-rw-r--r--src/test/run-fail/fail-arg.rs2
-rw-r--r--src/test/run-fail/fail-parens.rs6
-rw-r--r--src/test/run-fail/issue-1459.rs2
-rw-r--r--src/test/run-fail/issue-2444.rs2
-rw-r--r--src/test/run-fail/issue-948.rs2
-rw-r--r--src/test/run-fail/unique-fail.rs2
-rw-r--r--src/test/run-pass/region-dependent-addr-of.rs6
37 files changed, 109 insertions, 145 deletions
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 7a5b8dfd004..300d1600f2f 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!();
     }
 }
 ~~~~~~~~
@@ -989,13 +989,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$.
@@ -1007,7 +1007,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 {
@@ -2291,9 +2291,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")
 }
 ~~~~
 
@@ -2330,7 +2330,7 @@ match x {
         return;
     }
     _ => {
-        fail;
+        die!();
     }
 }
 ~~~~
@@ -2418,23 +2418,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}
@@ -3154,7 +3141,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/libcore/pipes.rs b/src/libcore/pipes.rs
index 15d118a9a7f..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());
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/libfuzzer/fuzzer.rc b/src/libfuzzer/fuzzer.rc
index 8b1ac845f4f..566ff65b15e 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/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 2443f426ee4..2af88b31642 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/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 db5ddfb9257..7ad1aaf364a 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -2859,7 +2859,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))
     }
 }
 
@@ -3205,7 +3205,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/mod.rs b/src/librustc/middle/typeck/check/mod.rs
index add1a132221..b81c0ffaf0b 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/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 7c947852afd..d92abe994db 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -690,7 +690,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>),
@@ -716,7 +716,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 e406e09aac0..ba6e2eeb938 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 0ab94710f40..e1204ccb4fe 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 51acf76ac30..84da60c0c90 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};
@@ -1031,12 +1031,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 72fd205fee9..6718a41e867 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/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/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/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/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!()
     }
 }