about summary refs log tree commit diff
path: root/src/libstd/rt/task.rs
diff options
context:
space:
mode:
authorMarvin Löbel <loebel.marvin@gmail.com>2013-10-27 20:12:40 +0100
committerMarvin Löbel <loebel.marvin@gmail.com>2013-10-30 21:19:18 +0100
commit54f4dcd76aafe33c553f6b58fe3e808f055465e1 (patch)
tree1a217bcb8ea4d3879dd86ece05468334af1754d2 /src/libstd/rt/task.rs
parente42e378f32e212997fc42281112b1c9c4c247de0 (diff)
downloadrust-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.rs71
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!()) }
 }