about summary refs log tree commit diff
path: root/src/libstd
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
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')
-rw-r--r--src/libstd/rt/borrowck.rs6
-rw-r--r--src/libstd/rt/kill.rs4
-rw-r--r--src/libstd/rt/task.rs71
-rw-r--r--src/libstd/std.rs5
-rw-r--r--src/libstd/sys.rs89
-rw-r--r--src/libstd/task/mod.rs48
-rw-r--r--src/libstd/task/spawn.rs7
-rw-r--r--src/libstd/unstable/lang.rs2
-rw-r--r--src/libstd/unstable/raw.rs30
9 files changed, 133 insertions, 129 deletions
diff --git a/src/libstd/rt/borrowck.rs b/src/libstd/rt/borrowck.rs
index 7fcd674009d..bd528cbe61f 100644
--- a/src/libstd/rt/borrowck.rs
+++ b/src/libstd/rt/borrowck.rs
@@ -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
diff --git a/src/libstd/rt/kill.rs b/src/libstd/rt/kill.rs
index edf6ffb820b..949421db9fc 100644
--- a/src/libstd/rt/kill.rs
+++ b/src/libstd/rt/kill.rs
@@ -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());
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!()) }
 }
diff --git a/src/libstd/std.rs b/src/libstd/std.rs
index 3a96cfb1171..df6c47a8492 100644
--- a/src/libstd/std.rs
+++ b/src/libstd/std.rs
@@ -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;
diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs
index b35b25aeb6f..4216f91b602 100644
--- a/src/libstd/sys.rs
+++ b/src/libstd/sys.rs
@@ -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 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);
-        }
+impl<T: Any + Send> FailWithCause for T {
+    fn fail_with(msg: T, file: &'static str, line: uint) -> ! {
+        task::begin_unwind(msg, file, line)
     }
-
-    #[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!()) }
 }
diff --git a/src/libstd/task/mod.rs b/src/libstd/task/mod.rs
index 023ba6f7108..cdb70f00dfe 100644
--- a/src/libstd/task/mod.rs
+++ b/src/libstd/task/mod.rs
@@ -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!()
diff --git a/src/libstd/task/spawn.rs b/src/libstd/task/spawn.rs
index a08bf8f3147..4a98e396bbc 100644
--- a/src/libstd/task/spawn.rs
+++ b/src/libstd/task/spawn.rs
@@ -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()")))
         }
     }
 }
diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs
index 89126bf9c9c..092e9b6d348 100644
--- a/src/libstd/unstable/lang.rs
+++ b/src/libstd/unstable/lang.rs
@@ -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]
diff --git a/src/libstd/unstable/raw.rs b/src/libstd/unstable/raw.rs
index 46e80f9f4e8..d784c1d38c6 100644
--- a/src/libstd/unstable/raw.rs
+++ b/src/libstd/unstable/raw.rs
@@ -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);
+        }
+    }
+}