diff options
| author | Marvin Löbel <loebel.marvin@gmail.com> | 2013-10-27 20:12:40 +0100 |
|---|---|---|
| committer | Marvin Löbel <loebel.marvin@gmail.com> | 2013-10-30 21:19:18 +0100 |
| commit | 54f4dcd76aafe33c553f6b58fe3e808f055465e1 (patch) | |
| tree | 1a217bcb8ea4d3879dd86ece05468334af1754d2 /src/libstd/rt/task.rs | |
| parent | e42e378f32e212997fc42281112b1c9c4c247de0 (diff) | |
| download | rust-54f4dcd76aafe33c553f6b58fe3e808f055465e1.tar.gz rust-54f4dcd76aafe33c553f6b58fe3e808f055465e1.zip | |
Prepared `std::sys` for removal, and made `begin_unwind` simpler
- `begin_unwind` is now generic over any `T: Any + Send`. - Every value you fail with gets boxed as an `~Any`. - Because of implementation details, `&'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.
Diffstat (limited to 'src/libstd/rt/task.rs')
| -rw-r--r-- | src/libstd/rt/task.rs | 71 |
1 files changed, 52 insertions, 19 deletions
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs index 516a795a1ad..b56dd0809df 100644 --- a/src/libstd/rt/task.rs +++ b/src/libstd/rt/task.rs @@ -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!()) } } |
