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 | |
| 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')
| -rw-r--r-- | src/libstd/rt/borrowck.rs | 6 | ||||
| -rw-r--r-- | src/libstd/rt/kill.rs | 4 | ||||
| -rw-r--r-- | src/libstd/rt/task.rs | 71 | ||||
| -rw-r--r-- | src/libstd/std.rs | 5 | ||||
| -rw-r--r-- | src/libstd/sys.rs | 89 | ||||
| -rw-r--r-- | src/libstd/task/mod.rs | 48 | ||||
| -rw-r--r-- | src/libstd/task/spawn.rs | 7 | ||||
| -rw-r--r-- | src/libstd/unstable/lang.rs | 2 | ||||
| -rw-r--r-- | src/libstd/unstable/raw.rs | 30 |
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); + } + } +} |
