Skip to content

Commit

Permalink
Prepared std::sys for removal, and made begin_unwind simpler
Browse files Browse the repository at this point in the history
- `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.
  • Loading branch information
Kimundi committed Oct 30, 2013
1 parent e42e378 commit 54f4dcd
Show file tree
Hide file tree
Showing 16 changed files with 187 additions and 229 deletions.
2 changes: 2 additions & 0 deletions src/libextra/extra.rs
Expand Up @@ -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;
Expand Down
6 changes: 3 additions & 3 deletions src/libstd/rt/borrowck.rs
Expand Up @@ -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
Expand All @@ -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)
}
}
}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/rt/kill.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -597,7 +597,7 @@ impl Death {
}

if !success {
result = Cell::new(Failure(UnwindReasonLinked));
result = Cell::new(Failure(UnwindMessageLinked));
}
}
on_exit(result.take());
Expand Down
71 changes: 52 additions & 19 deletions src/libstd/rt/task.rs
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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;
Expand All @@ -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();
}

Expand All @@ -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]
Expand Down Expand Up @@ -804,4 +833,8 @@ mod test {
a.next = Some(b);
}
}

#[test]
#[should_fail]
fn test_begin_unwind() { begin_unwind("cause", file!(), line!()) }
}
5 changes: 5 additions & 0 deletions src/libstd/std.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
89 changes: 5 additions & 84 deletions src/libstd/sys.rs
Expand Up @@ -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!()) }
}

5 comments on commit 54f4dcd

@bors
Copy link
Contributor

@bors bors commented on 54f4dcd Oct 31, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from alexcrichton
at Kimundi@54f4dcd

@bors
Copy link
Contributor

@bors bors commented on 54f4dcd Oct 31, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging Kimundi/rust/remove_sys = 54f4dcd into auto

@bors
Copy link
Contributor

@bors bors commented on 54f4dcd Oct 31, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kimundi/rust/remove_sys = 54f4dcd merged ok, testing candidate = f73a48e

@bors
Copy link
Contributor

@bors bors commented on 54f4dcd Oct 31, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bors
Copy link
Contributor

@bors bors commented on 54f4dcd Oct 31, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = f73a48e

Please sign in to comment.