Skip to content

Commit 9ef23e9

Browse files
committed
auto merge of #9967 : Kimundi/rust/fail_cause_two, r=huonw
# Summary This PR allows the cause of a failure to be received in a task's future result and as the `Err` case of `task::try`, and also implements dynamic typing in form of an `Any` trait. # Task failure - `fail!` and related macros now accept 5 kinds of types: `~str`, `&'static str`, `std::send_str::SendStr`, `~std::any::Any` and `~T` where `T: Any + Send + 'static` - `std::task::TaskResult` got transformed into an internal enum `std::rt::task::UnwindResult`, and it's `Failure` variant now contains a value of enum type `UnwindReason`: - `UnwindReasonStr(SendStr)` maps to failing with a value of type `~str`, `&'static str` or `SendStr`. - `UnwindReasonAny(~Any)` maps to failing with an `~Any` or `~T` with `T: Send + 'static`. - `UnwindReasonLinked` maps to failing because the task got killed by linked failure. - Instead, `std::task::TaskResult` is now a typedef for `Result<(), ~Any>`, and both `TaskBuilder`'s `future_result()` and `task::try` now work with a value of this type. - `future_result()` no longer returns a `Port<TaskResult>`, instead it returns a wrapper `TaskResultPort` that implements `GenericPort` and `Peekable`, and which lazily allocates a `~` box and casts to `~Any` in case of failure with a `SendStr` or linked failure (for the latter case a unit struct `LinkedFailure` got added.) - Because `fail!` collapses both `~str` and `&'static str` into a `SendStr`, checking if a task error value is a string will just require a `.is::<SendStr>()` check, with `~str` and `&'static str` only being possible in case of an explicit `fail!(~~"...")` or `fail!(~ (&"...") as ~Any)`: # Any - In order to allow failing with arbitrary data, the `Any` trait got implemented. - It is being used in form of a trait object, usually `~Any` or `&Any`. - `&Any`, `~Any` and `&mut Any` have a few extension methods implemented on them: - `is<T>(self) -> bool` returns true if the `Any` object contains type `T` - `as_ref<T>(self) -> Option<&T>` returns a reference to the contained type, if it is `T` - `as_mut<T>(self) -> Option<&mut T>` returns a mutable reference to the contained type, if it is `T` - `move<T>(self) -> Option<~T>` allows to get the `~T` out of an `~Any` again. - `Any` currently uses type descriptors as a type id for comparisons, which is - not reliable, as it is not guaranteed that every type has only one type descriptor. - But safe, as no two types share the same type descriptor. - The implementation also a few `transmute`s, mostly to cast a `*Void` of the wrapped type into it's actual type `&T`, `&mut T` or `~T`. # Other changes - `std::unstable::UnsafeArc::try_unwrap` no longer uses `Either`, bringing us one step closer to removing that type. - A few of the touched modules got their import lines sorted. - A few stylistic cleanups here and there.
2 parents cb5b21e + fa8e71a commit 9ef23e9

24 files changed

+912
-214
lines changed

Diff for: src/libextra/sync.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -918,7 +918,7 @@ mod tests {
918918
let m = Mutex::new();
919919
let m2 = m.clone();
920920

921-
let result: result::Result<(),()> = do task::try {
921+
let result: result::Result<(), ~Any> = do task::try {
922922
do m2.lock {
923923
fail!();
924924
}
@@ -935,7 +935,7 @@ mod tests {
935935
let m = Mutex::new();
936936
let m2 = m.clone();
937937

938-
let result: result::Result<(),()> = do task::try {
938+
let result: result::Result<(), ~Any> = do task::try {
939939
let (p, c) = comm::stream();
940940
do task::spawn || { // linked
941941
let _ = p.recv(); // wait for sibling to get in the mutex
@@ -963,7 +963,7 @@ mod tests {
963963
let m2 = m.clone();
964964
let (p, c) = comm::stream();
965965

966-
let result: result::Result<(),()> = do task::try {
966+
let result: result::Result<(), ~Any> = do task::try {
967967
let mut sibling_convos = ~[];
968968
do 2.times {
969969
let (p, c) = comm::stream();
@@ -1272,7 +1272,7 @@ mod tests {
12721272
let x = RWLock::new();
12731273
let x2 = x.clone();
12741274

1275-
let result: result::Result<(),()> = do task::try || {
1275+
let result: result::Result<(), ~Any> = do task::try || {
12761276
do lock_rwlock_in_mode(&x2, mode1) {
12771277
fail!();
12781278
}

Diff for: src/libextra/test.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -873,8 +873,7 @@ pub fn run_test(force_ignore: bool,
873873
task.spawn(testfn_cell.take());
874874

875875
let task_result = result_future.recv();
876-
let test_result = calc_result(&desc,
877-
task_result == task::Success);
876+
let test_result = calc_result(&desc, task_result.is_ok());
878877
monitor_ch.send((desc.clone(), test_result));
879878
}
880879
}

Diff for: src/librustpkg/tests.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -640,9 +640,8 @@ fn test_install_invalid() {
640640
pkgid.clone());
641641
ctxt.install(pkg_src, &WhatToBuild::new(MaybeCustom, Everything));
642642
};
643-
// Not the best test -- doesn't test that we failed in the right way.
644-
// Best we can do for now.
645-
assert!(result == Err(()));
643+
assert!(result.unwrap_err()
644+
.to_str().contains("supplied path for package dir does not exist"));
646645
}
647646

648647
#[test]

0 commit comments

Comments
 (0)