auto merge of #10120 : Kimundi/rust/remove_sys, r=alexcrichton
- `begin_unwind` and `fail!` is now generic over any `T: Any + Send`. - Every value you fail with gets boxed as an `~Any`. - Because of implementation issues, `&'static str` and `~str` are still handled specially behind the scenes. - Changed the big macro source string in libsyntax to a raw string literal, and enabled doc comments there.
This commit is contained in:
commit
f73a48e9fd
@ -118,6 +118,8 @@ pub mod extra {
|
||||
pub use std::clone;
|
||||
pub use std::condition;
|
||||
pub use std::cmp;
|
||||
// NOTE: Remove import after next snapshot
|
||||
#[cfg(stage0)]
|
||||
pub use std::sys;
|
||||
pub use std::unstable;
|
||||
pub use std::str;
|
||||
|
@ -65,7 +65,7 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) ->
|
||||
None => { // not recording borrows
|
||||
let msg = "borrowed";
|
||||
do msg.with_c_str |msg_p| {
|
||||
task::begin_unwind(msg_p, file, line);
|
||||
task::begin_unwind_raw(msg_p, file, line);
|
||||
}
|
||||
}
|
||||
Some(borrow_list) => { // recording borrows
|
||||
@ -81,7 +81,7 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) ->
|
||||
}
|
||||
}
|
||||
do msg.with_c_str |msg_p| {
|
||||
task::begin_unwind(msg_p, file, line)
|
||||
task::begin_unwind_raw(msg_p, file, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -180,7 +180,7 @@ pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint,
|
||||
if br.box != a || br.file != file || br.line != line {
|
||||
let err = format!("wrong borrow found, br={:?}", br);
|
||||
do err.with_c_str |msg_p| {
|
||||
task::begin_unwind(msg_p, file, line)
|
||||
task::begin_unwind_raw(msg_p, file, line)
|
||||
}
|
||||
}
|
||||
borrow_list
|
||||
|
@ -155,7 +155,7 @@ use cell::Cell;
|
||||
use option::{Option, Some, None};
|
||||
use prelude::*;
|
||||
use rt::task::Task;
|
||||
use rt::task::UnwindReasonLinked;
|
||||
use rt::task::UnwindMessageLinked;
|
||||
use rt::task::{UnwindResult, Failure};
|
||||
use task::spawn::Taskgroup;
|
||||
use to_bytes::IterBytes;
|
||||
@ -597,7 +597,7 @@ impl Death {
|
||||
}
|
||||
|
||||
if !success {
|
||||
result = Cell::new(Failure(UnwindReasonLinked));
|
||||
result = Cell::new(Failure(UnwindMessageLinked));
|
||||
}
|
||||
}
|
||||
on_exit(result.take());
|
||||
|
@ -95,8 +95,8 @@ pub enum UnwindResult {
|
||||
/// The task is ending successfully
|
||||
Success,
|
||||
|
||||
/// The Task is failing with reason `UnwindReason`
|
||||
Failure(UnwindReason),
|
||||
/// The Task is failing with reason `UnwindMessage`
|
||||
Failure(UnwindMessage),
|
||||
}
|
||||
|
||||
impl UnwindResult {
|
||||
@ -121,20 +121,25 @@ impl UnwindResult {
|
||||
|
||||
/// Represents the cause of a task failure
|
||||
#[deriving(ToStr)]
|
||||
pub enum UnwindReason {
|
||||
/// Failed with a string message
|
||||
UnwindReasonStr(SendStr),
|
||||
pub enum UnwindMessage {
|
||||
// FIXME: #9913 - This variant is not neccessary once Any works properly
|
||||
/// Failed with a static string message
|
||||
UnwindMessageStrStatic(&'static str),
|
||||
|
||||
// FIXME: #9913 - This variant is not neccessary once Any works properly
|
||||
/// Failed with a owned string message
|
||||
UnwindMessageStrOwned(~str),
|
||||
|
||||
/// Failed with an `~Any`
|
||||
UnwindReasonAny(~Any),
|
||||
UnwindMessageAny(~Any),
|
||||
|
||||
/// Failed because of linked failure
|
||||
UnwindReasonLinked
|
||||
UnwindMessageLinked
|
||||
}
|
||||
|
||||
pub struct Unwinder {
|
||||
unwinding: bool,
|
||||
cause: Option<UnwindReason>
|
||||
cause: Option<UnwindMessage>
|
||||
}
|
||||
|
||||
impl Unwinder {
|
||||
@ -527,7 +532,7 @@ impl Unwinder {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn begin_unwind(&mut self, cause: UnwindReason) -> ! {
|
||||
pub fn begin_unwind(&mut self, cause: UnwindMessage) -> ! {
|
||||
#[fixed_stack_segment]; #[inline(never)];
|
||||
|
||||
self.unwinding = true;
|
||||
@ -622,7 +627,7 @@ pub extern "C" fn rust_stack_exhausted() {
|
||||
/// This is the entry point of unwinding for things like lang items and such.
|
||||
/// The arguments are normally generated by the compiler, and need to
|
||||
/// have static lifetimes.
|
||||
pub fn begin_unwind(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
pub fn begin_unwind_raw(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
use c_str::CString;
|
||||
use cast::transmute;
|
||||
|
||||
@ -638,11 +643,33 @@ pub fn begin_unwind(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
let msg = static_char_ptr(msg);
|
||||
let file = static_char_ptr(file);
|
||||
|
||||
begin_unwind_reason(UnwindReasonStr(msg.into_send_str()), file, line as uint)
|
||||
begin_unwind(msg, file, line as uint)
|
||||
}
|
||||
|
||||
/// This is the entry point of unwinding for fail!() and assert!().
|
||||
pub fn begin_unwind_reason(reason: UnwindReason, file: &'static str, line: uint) -> ! {
|
||||
pub fn begin_unwind<M: Any + Send>(msg: M, file: &'static str, line: uint) -> ! {
|
||||
// Wrap the fail message in a `Any` box for uniform representation.
|
||||
let any = ~msg as ~Any;
|
||||
|
||||
// FIXME: #9913 - This can be changed to be internal to begin_unwind_internal
|
||||
// once Any works properly.
|
||||
// As a workaround, string types need to be special cased right now
|
||||
// because `Any` does not support dynamically querying whether the
|
||||
// type implements a trait yet, so without requiring that every `Any`
|
||||
// also implements `ToStr` there is no way to get a failure message
|
||||
// out of it again during unwinding.
|
||||
let msg = if any.is::<&'static str>() {
|
||||
UnwindMessageStrStatic(*any.move::<&'static str>().unwrap())
|
||||
} else if any.is::<~str>() {
|
||||
UnwindMessageStrOwned(*any.move::<~str>().unwrap())
|
||||
} else {
|
||||
UnwindMessageAny(any)
|
||||
};
|
||||
|
||||
begin_unwind_internal(msg, file, line)
|
||||
}
|
||||
|
||||
fn begin_unwind_internal(msg: UnwindMessage, file: &'static str, line: uint) -> ! {
|
||||
use rt::in_green_task_context;
|
||||
use rt::task::Task;
|
||||
use rt::local::Local;
|
||||
@ -656,15 +683,16 @@ pub fn begin_unwind_reason(reason: UnwindReason, file: &'static str, line: uint)
|
||||
let task: *mut Task;
|
||||
|
||||
{
|
||||
let msg = match reason {
|
||||
UnwindReasonStr(ref s) => s.as_slice(),
|
||||
UnwindReasonAny(_) => "~Any",
|
||||
UnwindReasonLinked => "linked failure",
|
||||
let msg_s = match msg {
|
||||
UnwindMessageAny(_) => "~Any",
|
||||
UnwindMessageLinked => "linked failure",
|
||||
UnwindMessageStrOwned(ref s) => s.as_slice(),
|
||||
UnwindMessageStrStatic(ref s) => s.as_slice(),
|
||||
};
|
||||
|
||||
if !in_green_task_context() {
|
||||
rterrln!("failed in non-task context at '{}', {}:{}",
|
||||
msg, file, line);
|
||||
msg_s, file, line);
|
||||
intrinsics::abort();
|
||||
}
|
||||
|
||||
@ -679,19 +707,20 @@ pub fn begin_unwind_reason(reason: UnwindReason, file: &'static str, line: uint)
|
||||
// due to mismanagment of its own kill flag, so calling our own
|
||||
// logger in its current state is a bit of a problem.
|
||||
|
||||
rterrln!("task '{}' failed at '{}', {}:{}", n, msg, file, line);
|
||||
rterrln!("task '{}' failed at '{}', {}:{}", n, msg_s, file, line);
|
||||
|
||||
if (*task).unwinder.unwinding {
|
||||
rtabort!("unwinding again");
|
||||
}
|
||||
}
|
||||
|
||||
(*task).unwinder.begin_unwind(reason);
|
||||
(*task).unwinder.begin_unwind(msg);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use rt::test::*;
|
||||
|
||||
#[test]
|
||||
@ -804,4 +833,8 @@ mod test {
|
||||
a.next = Some(b);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn test_begin_unwind() { begin_unwind("cause", file!(), line!()) }
|
||||
}
|
||||
|
@ -184,6 +184,8 @@ pub mod os;
|
||||
pub mod path;
|
||||
pub mod rand;
|
||||
pub mod run;
|
||||
// NOTE: Remove module after next snapshot
|
||||
#[cfg(stage0)]
|
||||
pub mod sys;
|
||||
pub mod cast;
|
||||
pub mod fmt;
|
||||
@ -226,7 +228,10 @@ mod std {
|
||||
pub use logging;
|
||||
pub use option;
|
||||
pub use os;
|
||||
pub use rt;
|
||||
pub use str;
|
||||
// NOTE: Remove import after next snapshot
|
||||
#[cfg(stage0)]
|
||||
pub use sys;
|
||||
pub use to_bytes;
|
||||
pub use to_str;
|
||||
|
@ -10,99 +10,20 @@
|
||||
|
||||
//! Misc low level stuff
|
||||
|
||||
// NOTE: Remove this module after an snapshot
|
||||
|
||||
#[allow(missing_doc)];
|
||||
|
||||
use any::Any;
|
||||
use kinds::Send;
|
||||
use rt::task::{UnwindReasonStr, UnwindReasonAny};
|
||||
use rt::task;
|
||||
use send_str::{SendStr, IntoSendStr};
|
||||
|
||||
/// Trait for initiating task failure with a sendable cause.
|
||||
pub trait FailWithCause {
|
||||
/// Fail the current task with `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) -> ! {
|
||||
task::begin_unwind_reason(UnwindReasonStr(cause.into_send_str()), file, line)
|
||||
impl<T: Any + Send> FailWithCause for T {
|
||||
fn fail_with(msg: T, file: &'static str, line: uint) -> ! {
|
||||
task::begin_unwind(msg, file, line)
|
||||
}
|
||||
}
|
||||
|
||||
impl FailWithCause for &'static str {
|
||||
fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
|
||||
task::begin_unwind_reason(UnwindReasonStr(cause.into_send_str()), file, line)
|
||||
}
|
||||
}
|
||||
|
||||
impl FailWithCause for SendStr {
|
||||
fn fail_with(cause: SendStr, file: &'static str, line: uint) -> ! {
|
||||
task::begin_unwind_reason(UnwindReasonStr(cause), file, line)
|
||||
}
|
||||
}
|
||||
|
||||
impl FailWithCause for ~Any {
|
||||
fn fail_with(cause: ~Any, file: &'static str, line: uint) -> ! {
|
||||
task::begin_unwind_reason(UnwindReasonAny(cause), file, line)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Any + Send + 'static> FailWithCause for ~T {
|
||||
fn fail_with(cause: ~T, file: &'static str, line: uint) -> ! {
|
||||
task::begin_unwind_reason(UnwindReasonAny(cause as ~Any), file, line)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use any::Any;
|
||||
use cast;
|
||||
use send_str::IntoSendStr;
|
||||
|
||||
#[test]
|
||||
fn synthesize_closure() {
|
||||
use unstable::raw::Closure;
|
||||
unsafe {
|
||||
let x = 10;
|
||||
let f: &fn(int) -> int = |y| x + y;
|
||||
|
||||
assert_eq!(f(20), 30);
|
||||
|
||||
let original_closure: Closure = cast::transmute(f);
|
||||
|
||||
let actual_function_pointer = original_closure.code;
|
||||
let environment = original_closure.env;
|
||||
|
||||
let new_closure = Closure {
|
||||
code: actual_function_pointer,
|
||||
env: environment
|
||||
};
|
||||
|
||||
let new_f: &fn(int) -> int = cast::transmute(new_closure);
|
||||
assert_eq!(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!()) }
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn fail_send() { FailWithCause::fail_with("cause".into_send_str(), file!(), line!()) }
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn fail_any() { FailWithCause::fail_with(~612_u16 as ~Any, file!(), line!()) }
|
||||
|
||||
#[test]
|
||||
#[should_fail]
|
||||
fn fail_any_wrap() { FailWithCause::fail_with(~413_u16, file!(), line!()) }
|
||||
}
|
||||
|
@ -60,7 +60,8 @@ use comm::{stream, Chan, GenericChan, GenericPort, Port, Peekable};
|
||||
use result::{Result, Ok, Err};
|
||||
use rt::in_green_task_context;
|
||||
use rt::local::Local;
|
||||
use rt::task::{UnwindReasonAny, UnwindReasonLinked, UnwindReasonStr};
|
||||
use rt::task::{UnwindMessageAny, UnwindMessageLinked};
|
||||
use rt::task::{UnwindMessageStrStatic, UnwindMessageStrOwned};
|
||||
use rt::task::{UnwindResult, Success, Failure};
|
||||
use send_str::{SendStr, IntoSendStr};
|
||||
use unstable::finally::Finally;
|
||||
@ -93,9 +94,10 @@ pub struct LinkedFailure;
|
||||
fn wrap_as_any(res: UnwindResult) -> TaskResult {
|
||||
match res {
|
||||
Success => Ok(()),
|
||||
Failure(UnwindReasonStr(s)) => Err(~s as ~Any),
|
||||
Failure(UnwindReasonAny(a)) => Err(a),
|
||||
Failure(UnwindReasonLinked) => Err(~LinkedFailure as ~Any)
|
||||
Failure(UnwindMessageAny(a)) => Err(a),
|
||||
Failure(UnwindMessageLinked) => Err(~LinkedFailure as ~Any),
|
||||
Failure(UnwindMessageStrOwned(s)) => Err(~s as ~Any),
|
||||
Failure(UnwindMessageStrStatic(s)) => Err(~s as ~Any),
|
||||
}
|
||||
}
|
||||
|
||||
@ -1425,38 +1427,52 @@ fn test_indestructible() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_fail_cause_static_str() {
|
||||
fn test_try_fail_message_static_str() {
|
||||
match do try {
|
||||
fail!("static string");
|
||||
} {
|
||||
Err(ref e) if e.is::<SendStr>() => {}
|
||||
Err(_) | Ok(()) => fail!()
|
||||
Err(e) => {
|
||||
type T = &'static str;
|
||||
assert!(e.is::<T>());
|
||||
assert_eq!(*e.move::<T>().unwrap(), "static string");
|
||||
}
|
||||
Ok(()) => fail!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_fail_cause_owned_str() {
|
||||
fn test_try_fail_message_owned_str() {
|
||||
match do try {
|
||||
fail!(~"owned string");
|
||||
} {
|
||||
Err(ref e) if e.is::<SendStr>() => {}
|
||||
Err(_) | Ok(()) => fail!()
|
||||
Err(e) => {
|
||||
type T = ~str;
|
||||
assert!(e.is::<T>());
|
||||
assert_eq!(*e.move::<T>().unwrap(), ~"owned string");
|
||||
}
|
||||
Ok(()) => fail!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_fail_cause_any() {
|
||||
fn test_try_fail_message_any() {
|
||||
match do try {
|
||||
fail!(~413u16 as ~Any);
|
||||
} {
|
||||
Err(ref e) if e.is::<u16>() => {}
|
||||
Err(_) | Ok(()) => fail!()
|
||||
Err(e) => {
|
||||
type T = ~Any;
|
||||
assert!(e.is::<T>());
|
||||
let any = e.move::<T>().unwrap();
|
||||
assert!(any.is::<u16>());
|
||||
assert_eq!(*any.move::<u16>().unwrap(), 413u16);
|
||||
}
|
||||
Ok(()) => fail!()
|
||||
}
|
||||
}
|
||||
|
||||
#[ignore(reason = "linked failure")]
|
||||
#[test]
|
||||
fn test_try_fail_cause_linked() {
|
||||
fn test_try_fail_message_linked() {
|
||||
match do try {
|
||||
do spawn {
|
||||
fail!()
|
||||
@ -1468,11 +1484,11 @@ fn test_try_fail_cause_linked() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_fail_cause_any_wrapped() {
|
||||
fn test_try_fail_message_unit_struct() {
|
||||
struct Juju;
|
||||
|
||||
match do try {
|
||||
fail!(~Juju)
|
||||
fail!(Juju)
|
||||
} {
|
||||
Err(ref e) if e.is::<Juju>() => {}
|
||||
Err(_) | Ok(()) => fail!()
|
||||
|
@ -83,12 +83,11 @@ use local_data;
|
||||
use rt::local::Local;
|
||||
use rt::sched::{Scheduler, Shutdown, TaskFromFriend};
|
||||
use rt::task::{Task, Sched};
|
||||
use rt::task::{UnwindReasonLinked, UnwindReasonStr};
|
||||
use rt::task::{UnwindMessageLinked, UnwindMessageStrStatic};
|
||||
use rt::task::{UnwindResult, Success, Failure};
|
||||
use rt::thread::Thread;
|
||||
use rt::work_queue::WorkQueue;
|
||||
use rt::{in_green_task_context, new_event_loop, KillHandle};
|
||||
use send_str::IntoSendStr;
|
||||
use task::SingleThreaded;
|
||||
use task::TaskOpts;
|
||||
use task::unkillable;
|
||||
@ -325,7 +324,7 @@ impl Drop for Taskgroup {
|
||||
do RuntimeGlue::with_task_handle_and_failing |me, failing| {
|
||||
if failing {
|
||||
for x in self.notifier.mut_iter() {
|
||||
x.task_result = Some(Failure(UnwindReasonLinked));
|
||||
x.task_result = Some(Failure(UnwindMessageLinked));
|
||||
}
|
||||
// Take everybody down with us. After this point, every
|
||||
// other task in the group will see 'tg' as none, which
|
||||
@ -380,7 +379,7 @@ impl AutoNotify {
|
||||
notify_chan: chan,
|
||||
|
||||
// Un-set above when taskgroup successfully made.
|
||||
task_result: Some(Failure(UnwindReasonStr("AutoNotify::new()".into_send_str())))
|
||||
task_result: Some(Failure(UnwindMessageStrStatic("AutoNotify::new()")))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ use rt::borrowck;
|
||||
#[cold]
|
||||
#[lang="fail_"]
|
||||
pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
task::begin_unwind(expr, file, line);
|
||||
task::begin_unwind_raw(expr, file, line);
|
||||
}
|
||||
|
||||
#[cold]
|
||||
|
@ -62,3 +62,33 @@ impl Repr<*Box<String>> for @str {}
|
||||
|
||||
// sure would be nice to have this
|
||||
// impl<T> Repr<*Vec<T>> for ~[T] {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use cast;
|
||||
|
||||
#[test]
|
||||
fn synthesize_closure() {
|
||||
unsafe {
|
||||
let x = 10;
|
||||
let f: &fn(int) -> int = |y| x + y;
|
||||
|
||||
assert_eq!(f(20), 30);
|
||||
|
||||
let original_closure: Closure = cast::transmute(f);
|
||||
|
||||
let actual_function_pointer = original_closure.code;
|
||||
let environment = original_closure.env;
|
||||
|
||||
let new_closure = Closure {
|
||||
code: actual_function_pointer,
|
||||
env: environment
|
||||
};
|
||||
|
||||
let new_f: &fn(int) -> int = cast::transmute(new_closure);
|
||||
assert_eq!(new_f(20), 30);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -604,9 +604,9 @@ impl AstBuilder for @ExtCtxt {
|
||||
span,
|
||||
~[
|
||||
self.ident_of("std"),
|
||||
self.ident_of("sys"),
|
||||
self.ident_of("FailWithCause"),
|
||||
self.ident_of("fail_with"),
|
||||
self.ident_of("rt"),
|
||||
self.ident_of("task"),
|
||||
self.ident_of("begin_unwind"),
|
||||
],
|
||||
~[
|
||||
self.expr_str(span, msg),
|
||||
|
@ -763,8 +763,7 @@ pub fn new_span(cx: @ExtCtxt, sp: Span) -> Span {
|
||||
// syntax elements.
|
||||
|
||||
pub fn std_macros() -> @str {
|
||||
return
|
||||
@"mod __std_macros {
|
||||
@r#"mod __std_macros {
|
||||
#[macro_escape];
|
||||
#[doc(hidden)];
|
||||
|
||||
@ -789,31 +788,30 @@ pub fn std_macros() -> @str {
|
||||
|
||||
macro_rules! fail(
|
||||
() => (
|
||||
fail!(\"explicit failure\")
|
||||
fail!("explicit failure")
|
||||
);
|
||||
($fmt:expr) => (
|
||||
::std::sys::FailWithCause::fail_with($fmt, file!(), line!())
|
||||
($msg:expr) => (
|
||||
::std::rt::task::begin_unwind($msg, file!(), line!())
|
||||
);
|
||||
($fmt:expr, $($arg:tt)*) => (
|
||||
::std::sys::FailWithCause::fail_with(format!($fmt, $($arg)*), file!(), line!())
|
||||
::std::rt::task::begin_unwind(format!($fmt, $($arg)*), file!(), line!())
|
||||
)
|
||||
)
|
||||
|
||||
macro_rules! assert(
|
||||
($cond:expr) => {
|
||||
if !$cond {
|
||||
::std::sys::FailWithCause::fail_with(
|
||||
\"assertion failed: \" + stringify!($cond), file!(), line!())
|
||||
fail!("assertion failed: {:s}", stringify!($cond))
|
||||
}
|
||||
};
|
||||
($cond:expr, $msg:expr) => {
|
||||
if !$cond {
|
||||
::std::sys::FailWithCause::fail_with($msg, file!(), line!())
|
||||
fail!($msg)
|
||||
}
|
||||
};
|
||||
($cond:expr, $( $arg:expr ),+) => {
|
||||
if !$cond {
|
||||
::std::sys::FailWithCause::fail_with(format!( $($arg),+ ), file!(), line!())
|
||||
fail!( $($arg),+ )
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -826,9 +824,8 @@ pub fn std_macros() -> @str {
|
||||
// check both directions of equality....
|
||||
if !((*given_val == *expected_val) &&
|
||||
(*expected_val == *given_val)) {
|
||||
fail!(\"assertion failed: `(left == right) && (right == \
|
||||
left)` (left: `{:?}`, right: `{:?}`)\",
|
||||
*given_val, *expected_val);
|
||||
fail!("assertion failed: `(left == right) && (right == left)` \
|
||||
(left: `{:?}`, right: `{:?}`)", *given_val, *expected_val)
|
||||
}
|
||||
}
|
||||
)
|
||||
@ -846,7 +843,7 @@ pub fn std_macros() -> @str {
|
||||
given_val.approx_eq(&expected_val) &&
|
||||
expected_val.approx_eq(&given_val)
|
||||
) {
|
||||
fail!(\"left: {:?} does not approximately equal right: {:?}\",
|
||||
fail!("left: {:?} does not approximately equal right: {:?}",
|
||||
given_val, expected_val);
|
||||
}
|
||||
}
|
||||
@ -863,42 +860,37 @@ pub fn std_macros() -> @str {
|
||||
given_val.approx_eq_eps(&expected_val, &epsilon_val) &&
|
||||
expected_val.approx_eq_eps(&given_val, &epsilon_val)
|
||||
) {
|
||||
fail!(\"left: {:?} does not approximately equal right: \
|
||||
{:?} with epsilon: {:?}\",
|
||||
fail!("left: {:?} does not approximately equal right: \
|
||||
{:?} with epsilon: {:?}",
|
||||
given_val, expected_val, epsilon_val);
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
// FIXME(#6266): change the /* to /** when attributes are supported on macros
|
||||
// (Though even then—is it going to work according to the clear intent here?)
|
||||
/*
|
||||
A utility macro for indicating unreachable code. It will fail if
|
||||
executed. This is occasionally useful to put after loops that never
|
||||
terminate normally, but instead directly return from a function.
|
||||
|
||||
# Example
|
||||
|
||||
```rust
|
||||
fn choose_weighted_item(v: &[Item]) -> Item {
|
||||
assert!(!v.is_empty());
|
||||
let mut so_far = 0u;
|
||||
for v.each |item| {
|
||||
so_far += item.weight;
|
||||
if so_far > 100 {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
// The above loop always returns, so we must hint to the
|
||||
// type checker that it isn't possible to get down here
|
||||
unreachable!();
|
||||
}
|
||||
```
|
||||
|
||||
*/
|
||||
/// A utility macro for indicating unreachable code. It will fail if
|
||||
/// executed. This is occasionally useful to put after loops that never
|
||||
/// terminate normally, but instead directly return from a function.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```rust
|
||||
/// fn choose_weighted_item(v: &[Item]) -> Item {
|
||||
/// assert!(!v.is_empty());
|
||||
/// let mut so_far = 0u;
|
||||
/// for item in v.iter() {
|
||||
/// so_far += item.weight;
|
||||
/// if so_far > 100 {
|
||||
/// return item;
|
||||
/// }
|
||||
/// }
|
||||
/// // The above loop always returns, so we must hint to the
|
||||
/// // type checker that it isn't possible to get down here
|
||||
/// unreachable!();
|
||||
/// }
|
||||
/// ```
|
||||
macro_rules! unreachable (() => (
|
||||
fail!(\"internal error: entered unreachable code\");
|
||||
fail!("internal error: entered unreachable code");
|
||||
))
|
||||
|
||||
macro_rules! condition (
|
||||
@ -968,18 +960,18 @@ pub fn std_macros() -> @str {
|
||||
)
|
||||
)
|
||||
|
||||
// externfn! declares a wrapper for an external function.
|
||||
// It is intended to be used like:
|
||||
//
|
||||
// externfn!(#[nolink]
|
||||
// fn memcmp(cx: *u8, ct: *u8, n: u32) -> u32)
|
||||
//
|
||||
// Due to limitations in the macro parser, this pattern must be
|
||||
// implemented with 4 distinct patterns (with attrs / without
|
||||
// attrs CROSS with args / without ARGS).
|
||||
//
|
||||
// Also, this macro grammar allows for any number of return types
|
||||
// because I couldn't figure out the syntax to specify at most one.
|
||||
/// externfn! declares a wrapper for an external function.
|
||||
/// It is intended to be used like:
|
||||
///
|
||||
/// externfn!(#[nolink]
|
||||
/// fn memcmp(cx: *u8, ct: *u8, n: u32) -> u32)
|
||||
///
|
||||
/// Due to limitations in the macro parser, this pattern must be
|
||||
/// implemented with 4 distinct patterns (with attrs / without
|
||||
/// attrs CROSS with args / without ARGS).
|
||||
///
|
||||
/// Also, this macro grammar allows for any number of return types
|
||||
/// because I couldn't figure out the syntax to specify at most one.
|
||||
macro_rules! externfn(
|
||||
(fn $name:ident () $(-> $ret_ty:ty),*) => (
|
||||
pub unsafe fn $name() $(-> $ret_ty),* {
|
||||
@ -1045,7 +1037,7 @@ pub fn std_macros() -> @str {
|
||||
)
|
||||
)
|
||||
|
||||
}";
|
||||
}"#
|
||||
}
|
||||
|
||||
struct Injector {
|
||||
|
@ -1,13 +0,0 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:failed to find an implementation of trait std::sys::FailWithCause for int
|
||||
|
||||
fn main() { fail!(5); }
|
@ -1,12 +0,0 @@
|
||||
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:failed to find an implementation of trait std::sys::FailWithCause for ~[int]
|
||||
fn main() { fail!(~[0i]); }
|
@ -1,15 +0,0 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// error-pattern:failed at 'test-fail-send-str'
|
||||
|
||||
fn main() {
|
||||
fail!("test-fail-send-str".into_send_str());
|
||||
}
|
@ -25,6 +25,6 @@ pub fn main() {
|
||||
let _b = Foo;
|
||||
};
|
||||
|
||||
let s = x.unwrap_err().move::<SendStr>().unwrap();
|
||||
let s = x.unwrap_err().move::<&'static str>().unwrap();
|
||||
assert_eq!(s.as_slice(), "This failure should happen.");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user