auto merge of #10120 : Kimundi/rust/remove_sys, r=alexcrichton

- `begin_unwind` and `fail!` is now generic over any `T: Any + Send`.
- Every value you fail with gets boxed as an `~Any`.
- Because of implementation issues, `&'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.
This commit is contained in:
bors 2013-10-30 18:31:26 -07:00
commit f73a48e9fd
16 changed files with 187 additions and 229 deletions

View file

@ -118,6 +118,8 @@ pub mod extra {
pub use std::clone; pub use std::clone;
pub use std::condition; pub use std::condition;
pub use std::cmp; pub use std::cmp;
// NOTE: Remove import after next snapshot
#[cfg(stage0)]
pub use std::sys; pub use std::sys;
pub use std::unstable; pub use std::unstable;
pub use std::str; pub use std::str;

View file

@ -65,7 +65,7 @@ unsafe fn fail_borrowed(box: *mut raw::Box<()>, file: *c_char, line: size_t) ->
None => { // not recording borrows None => { // not recording borrows
let msg = "borrowed"; let msg = "borrowed";
do msg.with_c_str |msg_p| { 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 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| { 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 { if br.box != a || br.file != file || br.line != line {
let err = format!("wrong borrow found, br={:?}", br); let err = format!("wrong borrow found, br={:?}", br);
do err.with_c_str |msg_p| { do err.with_c_str |msg_p| {
task::begin_unwind(msg_p, file, line) task::begin_unwind_raw(msg_p, file, line)
} }
} }
borrow_list borrow_list

View file

@ -155,7 +155,7 @@ use cell::Cell;
use option::{Option, Some, None}; use option::{Option, Some, None};
use prelude::*; use prelude::*;
use rt::task::Task; use rt::task::Task;
use rt::task::UnwindReasonLinked; use rt::task::UnwindMessageLinked;
use rt::task::{UnwindResult, Failure}; use rt::task::{UnwindResult, Failure};
use task::spawn::Taskgroup; use task::spawn::Taskgroup;
use to_bytes::IterBytes; use to_bytes::IterBytes;
@ -597,7 +597,7 @@ impl Death {
} }
if !success { if !success {
result = Cell::new(Failure(UnwindReasonLinked)); result = Cell::new(Failure(UnwindMessageLinked));
} }
} }
on_exit(result.take()); on_exit(result.take());

View file

@ -95,8 +95,8 @@ pub enum UnwindResult {
/// The task is ending successfully /// The task is ending successfully
Success, Success,
/// The Task is failing with reason `UnwindReason` /// The Task is failing with reason `UnwindMessage`
Failure(UnwindReason), Failure(UnwindMessage),
} }
impl UnwindResult { impl UnwindResult {
@ -121,20 +121,25 @@ impl UnwindResult {
/// Represents the cause of a task failure /// Represents the cause of a task failure
#[deriving(ToStr)] #[deriving(ToStr)]
pub enum UnwindReason { pub enum UnwindMessage {
/// Failed with a string message // FIXME: #9913 - This variant is not neccessary once Any works properly
UnwindReasonStr(SendStr), /// 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` /// Failed with an `~Any`
UnwindReasonAny(~Any), UnwindMessageAny(~Any),
/// Failed because of linked failure /// Failed because of linked failure
UnwindReasonLinked UnwindMessageLinked
} }
pub struct Unwinder { pub struct Unwinder {
unwinding: bool, unwinding: bool,
cause: Option<UnwindReason> cause: Option<UnwindMessage>
} }
impl Unwinder { 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)]; #[fixed_stack_segment]; #[inline(never)];
self.unwinding = true; 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. /// 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 /// The arguments are normally generated by the compiler, and need to
/// have static lifetimes. /// 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 c_str::CString;
use cast::transmute; 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 msg = static_char_ptr(msg);
let file = static_char_ptr(file); 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!(). /// 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::in_green_task_context;
use rt::task::Task; use rt::task::Task;
use rt::local::Local; 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 task: *mut Task;
{ {
let msg = match reason { let msg_s = match msg {
UnwindReasonStr(ref s) => s.as_slice(), UnwindMessageAny(_) => "~Any",
UnwindReasonAny(_) => "~Any", UnwindMessageLinked => "linked failure",
UnwindReasonLinked => "linked failure", UnwindMessageStrOwned(ref s) => s.as_slice(),
UnwindMessageStrStatic(ref s) => s.as_slice(),
}; };
if !in_green_task_context() { if !in_green_task_context() {
rterrln!("failed in non-task context at '{}', {}:{}", rterrln!("failed in non-task context at '{}', {}:{}",
msg, file, line); msg_s, file, line);
intrinsics::abort(); 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 // due to mismanagment of its own kill flag, so calling our own
// logger in its current state is a bit of a problem. // 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 { if (*task).unwinder.unwinding {
rtabort!("unwinding again"); rtabort!("unwinding again");
} }
} }
(*task).unwinder.begin_unwind(reason); (*task).unwinder.begin_unwind(msg);
} }
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use super::*;
use rt::test::*; use rt::test::*;
#[test] #[test]
@ -804,4 +833,8 @@ mod test {
a.next = Some(b); a.next = Some(b);
} }
} }
#[test]
#[should_fail]
fn test_begin_unwind() { begin_unwind("cause", file!(), line!()) }
} }

View file

@ -184,6 +184,8 @@ pub mod os;
pub mod path; pub mod path;
pub mod rand; pub mod rand;
pub mod run; pub mod run;
// NOTE: Remove module after next snapshot
#[cfg(stage0)]
pub mod sys; pub mod sys;
pub mod cast; pub mod cast;
pub mod fmt; pub mod fmt;
@ -226,7 +228,10 @@ mod std {
pub use logging; pub use logging;
pub use option; pub use option;
pub use os; pub use os;
pub use rt;
pub use str; pub use str;
// NOTE: Remove import after next snapshot
#[cfg(stage0)]
pub use sys; pub use sys;
pub use to_bytes; pub use to_bytes;
pub use to_str; pub use to_str;

View file

@ -10,99 +10,20 @@
//! Misc low level stuff //! Misc low level stuff
// NOTE: Remove this module after an snapshot
#[allow(missing_doc)]; #[allow(missing_doc)];
use any::Any; use any::Any;
use kinds::Send; use kinds::Send;
use rt::task::{UnwindReasonStr, UnwindReasonAny};
use rt::task; use rt::task;
use send_str::{SendStr, IntoSendStr};
/// Trait for initiating task failure with a sendable cause.
pub trait FailWithCause { pub trait FailWithCause {
/// Fail the current task with `cause`.
fn fail_with(cause: Self, file: &'static str, line: uint) -> !; fn fail_with(cause: Self, file: &'static str, line: uint) -> !;
} }
impl FailWithCause for ~str { impl<T: Any + Send> FailWithCause for T {
fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! { fn fail_with(msg: T, file: &'static str, line: uint) -> ! {
task::begin_unwind_reason(UnwindReasonStr(cause.into_send_str()), file, line) task::begin_unwind(msg, 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);
}
}
#[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!()) }
}

View file

@ -60,7 +60,8 @@ use comm::{stream, Chan, GenericChan, GenericPort, Port, Peekable};
use result::{Result, Ok, Err}; use result::{Result, Ok, Err};
use rt::in_green_task_context; use rt::in_green_task_context;
use rt::local::Local; 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 rt::task::{UnwindResult, Success, Failure};
use send_str::{SendStr, IntoSendStr}; use send_str::{SendStr, IntoSendStr};
use unstable::finally::Finally; use unstable::finally::Finally;
@ -93,9 +94,10 @@ pub struct LinkedFailure;
fn wrap_as_any(res: UnwindResult) -> TaskResult { fn wrap_as_any(res: UnwindResult) -> TaskResult {
match res { match res {
Success => Ok(()), Success => Ok(()),
Failure(UnwindReasonStr(s)) => Err(~s as ~Any), Failure(UnwindMessageAny(a)) => Err(a),
Failure(UnwindReasonAny(a)) => Err(a), Failure(UnwindMessageLinked) => Err(~LinkedFailure as ~Any),
Failure(UnwindReasonLinked) => 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] #[test]
fn test_try_fail_cause_static_str() { fn test_try_fail_message_static_str() {
match do try { match do try {
fail!("static string"); fail!("static string");
} { } {
Err(ref e) if e.is::<SendStr>() => {} Err(e) => {
Err(_) | Ok(()) => fail!() type T = &'static str;
assert!(e.is::<T>());
assert_eq!(*e.move::<T>().unwrap(), "static string");
}
Ok(()) => fail!()
} }
} }
#[test] #[test]
fn test_try_fail_cause_owned_str() { fn test_try_fail_message_owned_str() {
match do try { match do try {
fail!(~"owned string"); fail!(~"owned string");
} { } {
Err(ref e) if e.is::<SendStr>() => {} Err(e) => {
Err(_) | Ok(()) => fail!() type T = ~str;
assert!(e.is::<T>());
assert_eq!(*e.move::<T>().unwrap(), ~"owned string");
}
Ok(()) => fail!()
} }
} }
#[test] #[test]
fn test_try_fail_cause_any() { fn test_try_fail_message_any() {
match do try { match do try {
fail!(~413u16 as ~Any); fail!(~413u16 as ~Any);
} { } {
Err(ref e) if e.is::<u16>() => {} Err(e) => {
Err(_) | Ok(()) => fail!() 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")] #[ignore(reason = "linked failure")]
#[test] #[test]
fn test_try_fail_cause_linked() { fn test_try_fail_message_linked() {
match do try { match do try {
do spawn { do spawn {
fail!() fail!()
@ -1468,11 +1484,11 @@ fn test_try_fail_cause_linked() {
} }
#[test] #[test]
fn test_try_fail_cause_any_wrapped() { fn test_try_fail_message_unit_struct() {
struct Juju; struct Juju;
match do try { match do try {
fail!(~Juju) fail!(Juju)
} { } {
Err(ref e) if e.is::<Juju>() => {} Err(ref e) if e.is::<Juju>() => {}
Err(_) | Ok(()) => fail!() Err(_) | Ok(()) => fail!()

View file

@ -83,12 +83,11 @@ use local_data;
use rt::local::Local; use rt::local::Local;
use rt::sched::{Scheduler, Shutdown, TaskFromFriend}; use rt::sched::{Scheduler, Shutdown, TaskFromFriend};
use rt::task::{Task, Sched}; use rt::task::{Task, Sched};
use rt::task::{UnwindReasonLinked, UnwindReasonStr}; use rt::task::{UnwindMessageLinked, UnwindMessageStrStatic};
use rt::task::{UnwindResult, Success, Failure}; use rt::task::{UnwindResult, Success, Failure};
use rt::thread::Thread; use rt::thread::Thread;
use rt::work_queue::WorkQueue; use rt::work_queue::WorkQueue;
use rt::{in_green_task_context, new_event_loop, KillHandle}; use rt::{in_green_task_context, new_event_loop, KillHandle};
use send_str::IntoSendStr;
use task::SingleThreaded; use task::SingleThreaded;
use task::TaskOpts; use task::TaskOpts;
use task::unkillable; use task::unkillable;
@ -325,7 +324,7 @@ impl Drop for Taskgroup {
do RuntimeGlue::with_task_handle_and_failing |me, failing| { do RuntimeGlue::with_task_handle_and_failing |me, failing| {
if failing { if failing {
for x in self.notifier.mut_iter() { 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 // Take everybody down with us. After this point, every
// other task in the group will see 'tg' as none, which // other task in the group will see 'tg' as none, which
@ -380,7 +379,7 @@ impl AutoNotify {
notify_chan: chan, notify_chan: chan,
// Un-set above when taskgroup successfully made. // Un-set above when taskgroup successfully made.
task_result: Some(Failure(UnwindReasonStr("AutoNotify::new()".into_send_str()))) task_result: Some(Failure(UnwindMessageStrStatic("AutoNotify::new()")))
} }
} }
} }

View file

@ -19,7 +19,7 @@ use rt::borrowck;
#[cold] #[cold]
#[lang="fail_"] #[lang="fail_"]
pub fn fail_(expr: *c_char, file: *c_char, line: size_t) -> ! { 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] #[cold]

View file

@ -62,3 +62,33 @@ impl Repr<*Box<String>> for @str {}
// sure would be nice to have this // sure would be nice to have this
// impl<T> Repr<*Vec<T>> for ~[T] {} // 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);
}
}
}

View file

@ -604,9 +604,9 @@ impl AstBuilder for @ExtCtxt {
span, span,
~[ ~[
self.ident_of("std"), self.ident_of("std"),
self.ident_of("sys"), self.ident_of("rt"),
self.ident_of("FailWithCause"), self.ident_of("task"),
self.ident_of("fail_with"), self.ident_of("begin_unwind"),
], ],
~[ ~[
self.expr_str(span, msg), self.expr_str(span, msg),

View file

@ -763,8 +763,7 @@ pub fn new_span(cx: @ExtCtxt, sp: Span) -> Span {
// syntax elements. // syntax elements.
pub fn std_macros() -> @str { pub fn std_macros() -> @str {
return @r#"mod __std_macros {
@"mod __std_macros {
#[macro_escape]; #[macro_escape];
#[doc(hidden)]; #[doc(hidden)];
@ -789,31 +788,30 @@ pub fn std_macros() -> @str {
macro_rules! fail( macro_rules! fail(
() => ( () => (
fail!(\"explicit failure\") fail!("explicit failure")
); );
($fmt:expr) => ( ($msg:expr) => (
::std::sys::FailWithCause::fail_with($fmt, file!(), line!()) ::std::rt::task::begin_unwind($msg, file!(), line!())
); );
($fmt:expr, $($arg:tt)*) => ( ($fmt:expr, $($arg:tt)*) => (
::std::sys::FailWithCause::fail_with(format!($fmt, $($arg)*), file!(), line!()) ::std::rt::task::begin_unwind(format!($fmt, $($arg)*), file!(), line!())
) )
) )
macro_rules! assert( macro_rules! assert(
($cond:expr) => { ($cond:expr) => {
if !$cond { if !$cond {
::std::sys::FailWithCause::fail_with( fail!("assertion failed: {:s}", stringify!($cond))
\"assertion failed: \" + stringify!($cond), file!(), line!())
} }
}; };
($cond:expr, $msg:expr) => { ($cond:expr, $msg:expr) => {
if !$cond { if !$cond {
::std::sys::FailWithCause::fail_with($msg, file!(), line!()) fail!($msg)
} }
}; };
($cond:expr, $( $arg:expr ),+) => { ($cond:expr, $( $arg:expr ),+) => {
if !$cond { if !$cond {
::std::sys::FailWithCause::fail_with(format!( $($arg),+ ), file!(), line!()) fail!( $($arg),+ )
} }
} }
) )
@ -826,9 +824,8 @@ pub fn std_macros() -> @str {
// check both directions of equality.... // check both directions of equality....
if !((*given_val == *expected_val) && if !((*given_val == *expected_val) &&
(*expected_val == *given_val)) { (*expected_val == *given_val)) {
fail!(\"assertion failed: `(left == right) && (right == \ fail!("assertion failed: `(left == right) && (right == left)` \
left)` (left: `{:?}`, right: `{:?}`)\", (left: `{:?}`, right: `{:?}`)", *given_val, *expected_val)
*given_val, *expected_val);
} }
} }
) )
@ -846,7 +843,7 @@ pub fn std_macros() -> @str {
given_val.approx_eq(&expected_val) && given_val.approx_eq(&expected_val) &&
expected_val.approx_eq(&given_val) expected_val.approx_eq(&given_val)
) { ) {
fail!(\"left: {:?} does not approximately equal right: {:?}\", fail!("left: {:?} does not approximately equal right: {:?}",
given_val, expected_val); given_val, expected_val);
} }
} }
@ -863,42 +860,37 @@ pub fn std_macros() -> @str {
given_val.approx_eq_eps(&expected_val, &epsilon_val) && given_val.approx_eq_eps(&expected_val, &epsilon_val) &&
expected_val.approx_eq_eps(&given_val, &epsilon_val) expected_val.approx_eq_eps(&given_val, &epsilon_val)
) { ) {
fail!(\"left: {:?} does not approximately equal right: \ fail!("left: {:?} does not approximately equal right: \
{:?} with epsilon: {:?}\", {:?} with epsilon: {:?}",
given_val, expected_val, epsilon_val); given_val, expected_val, epsilon_val);
} }
} }
) )
) )
// FIXME(#6266): change the /* to /** when attributes are supported on macros /// A utility macro for indicating unreachable code. It will fail if
// (Though even then—is it going to work according to the clear intent here?) /// executed. This is occasionally useful to put after loops that never
/* /// terminate normally, but instead directly return from a function.
A utility macro for indicating unreachable code. It will fail if ///
executed. This is occasionally useful to put after loops that never /// # Example
terminate normally, but instead directly return from a function. ///
/// ```rust
# Example /// fn choose_weighted_item(v: &[Item]) -> Item {
/// assert!(!v.is_empty());
```rust /// let mut so_far = 0u;
fn choose_weighted_item(v: &[Item]) -> Item { /// for item in v.iter() {
assert!(!v.is_empty()); /// so_far += item.weight;
let mut so_far = 0u; /// if so_far > 100 {
for v.each |item| { /// return item;
so_far += item.weight; /// }
if so_far > 100 { /// }
return item; /// // The above loop always returns, so we must hint to the
} /// // type checker that it isn't possible to get down here
} /// unreachable!();
// The above loop always returns, so we must hint to the /// }
// type checker that it isn't possible to get down here /// ```
unreachable!();
}
```
*/
macro_rules! unreachable (() => ( macro_rules! unreachable (() => (
fail!(\"internal error: entered unreachable code\"); fail!("internal error: entered unreachable code");
)) ))
macro_rules! condition ( macro_rules! condition (
@ -968,18 +960,18 @@ pub fn std_macros() -> @str {
) )
) )
// externfn! declares a wrapper for an external function. /// externfn! declares a wrapper for an external function.
// It is intended to be used like: /// It is intended to be used like:
// ///
// externfn!(#[nolink] /// externfn!(#[nolink]
// fn memcmp(cx: *u8, ct: *u8, n: u32) -> u32) /// fn memcmp(cx: *u8, ct: *u8, n: u32) -> u32)
// ///
// Due to limitations in the macro parser, this pattern must be /// Due to limitations in the macro parser, this pattern must be
// implemented with 4 distinct patterns (with attrs / without /// implemented with 4 distinct patterns (with attrs / without
// attrs CROSS with args / without ARGS). /// attrs CROSS with args / without ARGS).
// ///
// Also, this macro grammar allows for any number of return types /// Also, this macro grammar allows for any number of return types
// because I couldn't figure out the syntax to specify at most one. /// because I couldn't figure out the syntax to specify at most one.
macro_rules! externfn( macro_rules! externfn(
(fn $name:ident () $(-> $ret_ty:ty),*) => ( (fn $name:ident () $(-> $ret_ty:ty),*) => (
pub unsafe fn $name() $(-> $ret_ty),* { pub unsafe fn $name() $(-> $ret_ty),* {
@ -1045,7 +1037,7 @@ pub fn std_macros() -> @str {
) )
) )
}"; }"#
} }
struct Injector { struct Injector {

View file

@ -1,13 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:failed to find an implementation of trait std::sys::FailWithCause for int
fn main() { fail!(5); }

View file

@ -1,12 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:failed to find an implementation of trait std::sys::FailWithCause for ~[int]
fn main() { fail!(~[0i]); }

View file

@ -1,15 +0,0 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:failed at 'test-fail-send-str'
fn main() {
fail!("test-fail-send-str".into_send_str());
}

View file

@ -25,6 +25,6 @@ pub fn main() {
let _b = Foo; let _b = Foo;
}; };
let s = x.unwrap_err().move::<SendStr>().unwrap(); let s = x.unwrap_err().move::<&'static str>().unwrap();
assert_eq!(s.as_slice(), "This failure should happen."); assert_eq!(s.as_slice(), "This failure should happen.");
} }