Skip to content

Prepared std::sys for removal, and made begin_unwind simpler #10120

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 31, 2013
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/libextra/extra.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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 {
Copy link
Member

Choose a reason for hiding this comment

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

As below, can this be tagged as a FIXME pointing at 9913? It seems like this should be just ~Any

// 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) -> ! {
Copy link
Member

Choose a reason for hiding this comment

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

Because Any is defined for all T, does this actually need the Any bound?

fn foo<T: Send>(t: T) -> ~Any { ~t as ~Any }

Seems to compile for me, so I would hope that it could be removed.

// 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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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!()) }
}
Loading