From e1be9ae22468e19d66daaebbceeeeaea2e75f903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marvin=20L=C3=B6bel?= Date: Tue, 23 Apr 2013 22:30:58 +0200 Subject: [PATCH] Made fail! and assert! accept both &'static str and ~str, as well as a fmt! like format list. Unwinding through macros now happens as a call to the trait function `FailWithCause::fail_with()`, which consumes self, allowing to use a more generic failure object in the future. --- src/libcore/sys.rs | 47 ++++++++++++++++++++++- src/libsyntax/ext/auto_encode.rs | 2 +- src/libsyntax/ext/build.rs | 7 ++-- src/libsyntax/ext/expand.rs | 42 +++++++++++++------- src/test/compile-fail/die-not-static.rs | 7 ++++ src/test/compile-fail/die-not-unique.rs | 5 --- src/test/compile-fail/fail-expr.rs | 2 +- src/test/compile-fail/fail-type-err.rs | 2 +- src/test/run-fail/assert-eq-macro-fail.rs | 2 +- 9 files changed, 90 insertions(+), 26 deletions(-) create mode 100644 src/test/compile-fail/die-not-static.rs delete mode 100644 src/test/compile-fail/die-not-unique.rs diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs index c4ec83aa176..bdc3a17308d 100644 --- a/src/libcore/sys.rs +++ b/src/libcore/sys.rs @@ -165,7 +165,42 @@ pub fn log_str(t: &T) -> ~str { } } -/** Initiate task failure */ +/// Trait for initiating task failure. +pub trait FailWithCause { + /// Fail the current task, taking ownership of `cause` + fn fail_with(cause: Self, file: &'static str, line: uint) -> !; +} + +impl FailWithCause for ~str { + fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! { + do str::as_buf(cause) |msg_buf, _msg_len| { + do str::as_buf(file) |file_buf, _file_len| { + unsafe { + let msg_buf = cast::transmute(msg_buf); + let file_buf = cast::transmute(file_buf); + begin_unwind_(msg_buf, file_buf, line as libc::size_t) + } + } + } + } +} + +impl FailWithCause for &'static str { + fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! { + do str::as_buf(cause) |msg_buf, _msg_len| { + do str::as_buf(file) |file_buf, _file_len| { + unsafe { + let msg_buf = cast::transmute(msg_buf); + let file_buf = cast::transmute(file_buf); + begin_unwind_(msg_buf, file_buf, line as libc::size_t) + } + } + } + } +} + +// NOTE: remove function after snapshot +#[cfg(stage0)] pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! { do str::as_buf(msg) |msg_buf, _msg_len| { do str::as_buf(file) |file_buf, _file_len| { @@ -187,6 +222,8 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! { } } +// NOTE: remove function after snapshot +#[cfg(stage0)] pub fn fail_assert(msg: &str, file: &str, line: uint) -> ! { let (msg, file) = (msg.to_owned(), file.to_owned()); begin_unwind(~"assertion failed: " + msg, file, line) @@ -297,6 +334,14 @@ mod tests { assert!(new_f(20) == 30); } } + + #[test] + #[should_fail] + fn fail_static() { FailWithCause::fail_with("cause", file!(), line!()) } + + #[test] + #[should_fail] + fn fail_owned() { FailWithCause::fail_with(~"cause", file!(), line!()) } } // Local Variables: diff --git a/src/libsyntax/ext/auto_encode.rs b/src/libsyntax/ext/auto_encode.rs index 67c09c00733..8263fce2356 100644 --- a/src/libsyntax/ext/auto_encode.rs +++ b/src/libsyntax/ext/auto_encode.rs @@ -1101,7 +1101,7 @@ fn mk_enum_deser_body( }; let quoted_expr = copy quote_expr!( - ::core::sys::begin_unwind(~"explicit failure", ~"empty", 1); + ::core::sys::FailWithCause::fail_with("explicit failure", "empty", 1); ).node; let impossible_case = ast::arm { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index ff78ddb803c..db4929854b3 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -474,11 +474,12 @@ pub fn mk_unreachable(cx: @ext_ctxt, span: span) -> @ast::expr { ~[ cx.ident_of(~"core"), cx.ident_of(~"sys"), - cx.ident_of(~"begin_unwind"), + cx.ident_of(~"FailWithCause"), + cx.ident_of(~"fail_with"), ], ~[ - mk_uniq_str(cx, span, ~"internal error: entered unreachable code"), - mk_uniq_str(cx, span, loc.file.name), + mk_base_str(cx, span, ~"internal error: entered unreachable code"), + mk_base_str(cx, span, loc.file.name), mk_uint(cx, span, loc.line), ] ) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 61032429c93..53ebb946114 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -415,6 +415,7 @@ pub fn core_macros() -> ~str { __log(1u32, fmt!( $($arg),+ )) ) ) + macro_rules! warn ( ($arg:expr) => ( __log(2u32, fmt!( \"%?\", $arg )) @@ -423,6 +424,7 @@ pub fn core_macros() -> ~str { __log(2u32, fmt!( $($arg),+ )) ) ) + macro_rules! info ( ($arg:expr) => ( __log(3u32, fmt!( \"%?\", $arg )) @@ -431,6 +433,7 @@ pub fn core_macros() -> ~str { __log(3u32, fmt!( $($arg),+ )) ) ) + macro_rules! debug ( ($arg:expr) => ( __log(4u32, fmt!( \"%?\", $arg )) @@ -441,35 +444,48 @@ pub fn core_macros() -> ~str { ) macro_rules! fail( - ($msg: expr) => ( - ::core::sys::begin_unwind($msg, file!().to_owned(), line!()) - ); () => ( - fail!(~\"explicit failure\") + fail!(\"explicit failure\") + ); + ($msg:expr) => ( + ::core::sys::FailWithCause::fail_with($msg, file!(), line!()) + ); + ($( $arg:expr ),+) => ( + ::core::sys::FailWithCause::fail_with(fmt!( $($arg),+ ), file!(), line!()) ) ) macro_rules! assert( ($cond:expr) => { if !$cond { - ::core::sys::fail_assert(stringify!($cond), file!(), line!()) + ::core::sys::FailWithCause::fail_with( + ~\"assertion failed: \" + stringify!($cond), file!(), line!()) } }; ($cond:expr, $msg:expr) => { if !$cond { - ::core::sys::fail_assert($msg, file!(), line!()) + ::core::sys::FailWithCause::fail_with($msg, file!(), line!()) + } + }; + ($cond:expr, $( $arg:expr ),+) => { + if !$cond { + ::core::sys::FailWithCause::fail_with(fmt!( $($arg),+ ), file!(), line!()) } } ) macro_rules! assert_eq ( - ($given:expr , $expected:expr) => - ({let given_val = $given; - let expected_val = $expected; - // check both directions of equality.... - if !((given_val == expected_val) && (expected_val == given_val)) { - fail!(fmt!(\"expected: %?, given: %?\",expected_val,given_val)); - }})) + ($given:expr , $expected:expr) => ( + { + let given_val = $given; + let expected_val = $expected; + // check both directions of equality.... + if !((given_val == expected_val) && (expected_val == given_val)) { + fail!(fmt!(\"left: %? != right: %?\", given_val, expected_val)); + } + } + ) + ) macro_rules! condition ( diff --git a/src/test/compile-fail/die-not-static.rs b/src/test/compile-fail/die-not-static.rs new file mode 100644 index 00000000000..b30e3942e63 --- /dev/null +++ b/src/test/compile-fail/die-not-static.rs @@ -0,0 +1,7 @@ +// error-pattern:illegal borrow: borrowed value does not live long enough + +fn main() { + let v = ~"test"; + let sslice = str::slice(v, 0, v.len()); + fail!(sslice); +} diff --git a/src/test/compile-fail/die-not-unique.rs b/src/test/compile-fail/die-not-unique.rs deleted file mode 100644 index 29369f081d7..00000000000 --- a/src/test/compile-fail/die-not-unique.rs +++ /dev/null @@ -1,5 +0,0 @@ -// error-pattern:mismatched types - -fn main() { - fail!("test"); -} diff --git a/src/test/compile-fail/fail-expr.rs b/src/test/compile-fail/fail-expr.rs index 38a883d44db..e17c8d6a182 100644 --- a/src/test/compile-fail/fail-expr.rs +++ b/src/test/compile-fail/fail-expr.rs @@ -8,6 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:mismatched types +// error-pattern:failed to find an implementation of trait core::sys::FailWithCause for int fn main() { fail!(5); } diff --git a/src/test/compile-fail/fail-type-err.rs b/src/test/compile-fail/fail-type-err.rs index 664063b466b..fbfa85ea6f8 100644 --- a/src/test/compile-fail/fail-type-err.rs +++ b/src/test/compile-fail/fail-type-err.rs @@ -8,5 +8,5 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:expected `~str` but found `~[int]` +// error-pattern:failed to find an implementation of trait core::sys::FailWithCause for ~[int] fn main() { fail!(~[0i]); } diff --git a/src/test/run-fail/assert-eq-macro-fail.rs b/src/test/run-fail/assert-eq-macro-fail.rs index d3177e7c0a8..7d98d0dccde 100644 --- a/src/test/run-fail/assert-eq-macro-fail.rs +++ b/src/test/run-fail/assert-eq-macro-fail.rs @@ -1,4 +1,4 @@ -// error-pattern:expected: 15, given: 14 +// error-pattern:left: 14 != right: 15 #[deriving(Eq)] struct Point { x : int }