Remove std::condition
This has been a long time coming. Conditions in rust were initially envisioned
as being a good alternative to error code return pattern. The idea is that all
errors are fatal-by-default, and you can opt-in to handling the error by
registering an error handler.
While sounding nice, conditions ended up having some unforseen shortcomings:
* Actually handling an error has some very awkward syntax:
let mut result = None;
let mut answer = None;
io::io_error::cond.trap(|e| { result = Some(e) }).inside(|| {
answer = Some(some_io_operation());
});
match result {
Some(err) => { /* hit an I/O error */ }
None => {
let answer = answer.unwrap();
/* deal with the result of I/O */
}
}
This pattern can certainly use functions like io::result, but at its core
actually handling conditions is fairly difficult
* The "zero value" of a function is often confusing. One of the main ideas
behind using conditions was to change the signature of I/O functions. Instead
of read_be_u32() returning a result, it returned a u32. Errors were notified
via a condition, and if you caught the condition you understood that the "zero
value" returned is actually a garbage value. These zero values are often
difficult to understand, however.
One case of this is the read_bytes() function. The function takes an integer
length of the amount of bytes to read, and returns an array of that size. The
array may actually be shorter, however, if an error occurred.
Another case is fs::stat(). The theoretical "zero value" is a blank stat
struct, but it's a little awkward to create and return a zero'd out stat
struct on a call to stat().
In general, the return value of functions that can raise error are much more
natural when using a Result as opposed to an always-usable zero-value.
* Conditions impose a necessary runtime requirement on *all* I/O. In theory I/O
is as simple as calling read() and write(), but using conditions imposed the
restriction that a rust local task was required if you wanted to catch errors
with I/O. While certainly an surmountable difficulty, this was always a bit of
a thorn in the side of conditions.
* Functions raising conditions are not always clear that they are raising
conditions. This suffers a similar problem to exceptions where you don't
actually know whether a function raises a condition or not. The documentation
likely explains, but if someone retroactively adds a condition to a function
there's nothing forcing upstream users to acknowledge a new point of task
failure.
* Libaries using I/O are not guaranteed to correctly raise on conditions when an
error occurs. In developing various I/O libraries, it's much easier to just
return `None` from a read rather than raising an error. The silent contract of
"don't raise on EOF" was a little difficult to understand and threw a wrench
into the answer of the question "when do I raise a condition?"
Many of these difficulties can be overcome through documentation, examples, and
general practice. In the end, all of these difficulties added together ended up
being too overwhelming and improving various aspects didn't end up helping that
much.
A result-based I/O error handling strategy also has shortcomings, but the
cognitive burden is much smaller. The tooling necessary to make this strategy as
usable as conditions were is much smaller than the tooling necessary for
conditions.
Perhaps conditions may manifest themselves as a future entity, but for now
we're going to remove them from the standard library.
Closes #9795
Closes #8968
This commit is contained in:
parent
f039d10cf7
commit
454882dcb7
23 changed files with 91 additions and 1771 deletions
|
|
@ -1,19 +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.
|
||||
|
||||
#[crate_type="lib"];
|
||||
|
||||
condition! {
|
||||
pub oops: int -> int;
|
||||
}
|
||||
|
||||
pub fn trouble() -> int {
|
||||
oops::cond.raise(1)
|
||||
}
|
||||
|
|
@ -1,15 +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.
|
||||
|
||||
#[crate_type="lib"];
|
||||
|
||||
condition! {
|
||||
pub oops: int -> int;
|
||||
}
|
||||
|
|
@ -1,21 +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.
|
||||
|
||||
#[crate_type="lib"];
|
||||
|
||||
condition! {
|
||||
pub oops: int -> int;
|
||||
}
|
||||
|
||||
pub fn guard(k: extern fn() -> int, x: int) -> int {
|
||||
oops::cond.trap(|i| i*x).inside(|| {
|
||||
k()
|
||||
})
|
||||
}
|
||||
|
|
@ -1,28 +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.
|
||||
|
||||
#[crate_type="lib"];
|
||||
|
||||
#[deriving(Eq)]
|
||||
pub enum Color {
|
||||
Red, Green, Blue
|
||||
}
|
||||
|
||||
condition! {
|
||||
pub oops: (int,f64,~str) -> Color;
|
||||
}
|
||||
|
||||
pub trait Thunk<T> {
|
||||
fn call(self) -> T;
|
||||
}
|
||||
|
||||
pub fn callback<T,TH:Thunk<T>>(t:TH) -> T {
|
||||
t.call()
|
||||
}
|
||||
|
|
@ -24,9 +24,3 @@ pub fn verify_same2(a: &'static int) {
|
|||
let b = global2 as *int as uint;
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
condition!{ pub test: int -> (); }
|
||||
|
||||
pub fn raise() {
|
||||
test::cond.raise(3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,40 +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.
|
||||
|
||||
// xfail-fast
|
||||
// aux-build:xc_conditions.rs
|
||||
|
||||
extern mod xc_conditions;
|
||||
use xc_conditions::oops;
|
||||
use xc_conditions::trouble;
|
||||
|
||||
// Tests of cross-crate conditions; the condition is
|
||||
// defined in lib, and we test various combinations
|
||||
// of `trap` and `raise` in the client or the lib where
|
||||
// the condition was defined. Also in test #4 we use
|
||||
// more complex features (generics, traits) in
|
||||
// combination with the condition.
|
||||
//
|
||||
// trap raise
|
||||
// ------------
|
||||
// xc_conditions : client lib
|
||||
// xc_conditions_2: client client
|
||||
// xc_conditions_3: lib client
|
||||
// xc_conditions_4: client client (with traits)
|
||||
//
|
||||
// the trap=lib, raise=lib case isn't tested since
|
||||
// there's no cross-crate-ness to test in that case.
|
||||
|
||||
pub fn main() {
|
||||
oops::cond.trap(|_i| 12345).inside(|| {
|
||||
let x = trouble();
|
||||
assert_eq!(x,12345);
|
||||
})
|
||||
}
|
||||
|
|
@ -1,19 +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.
|
||||
|
||||
// xfail-fast
|
||||
// aux-build:xc_conditions_2.rs
|
||||
|
||||
extern mod xc_conditions_2;
|
||||
use xcc = xc_conditions_2;
|
||||
|
||||
pub fn main() {
|
||||
xcc::oops::cond.trap(|_| 1).inside(|| xcc::oops::cond.raise(1));
|
||||
}
|
||||
|
|
@ -1,38 +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.
|
||||
|
||||
// xfail-fast
|
||||
// aux-build:xc_conditions_3.rs
|
||||
|
||||
extern mod xc_conditions_3;
|
||||
use xcc = xc_conditions_3;
|
||||
|
||||
pub fn main() {
|
||||
assert_eq!(xcc::guard(a, 1), 40);
|
||||
}
|
||||
|
||||
pub fn a() -> int {
|
||||
assert_eq!(xcc::oops::cond.raise(7), 7);
|
||||
xcc::guard(b, 2)
|
||||
}
|
||||
|
||||
pub fn b() -> int {
|
||||
assert_eq!(xcc::oops::cond.raise(8), 16);
|
||||
xcc::guard(c, 3)
|
||||
}
|
||||
|
||||
pub fn c() -> int {
|
||||
assert_eq!(xcc::oops::cond.raise(9), 27);
|
||||
xcc::guard(d, 4)
|
||||
}
|
||||
|
||||
pub fn d() -> int {
|
||||
xcc::oops::cond.raise(10)
|
||||
}
|
||||
|
|
@ -1,32 +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.
|
||||
|
||||
// xfail-fast
|
||||
// aux-build:xc_conditions_4.rs
|
||||
|
||||
extern mod xc_conditions_4;
|
||||
use xcc = xc_conditions_4;
|
||||
|
||||
struct SThunk {
|
||||
x: int
|
||||
}
|
||||
|
||||
impl xcc::Thunk<xcc::Color> for SThunk {
|
||||
fn call(self) -> xcc::Color {
|
||||
xcc::oops::cond.raise((self.x, 1.23, ~"oh no"))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
xcc::oops::cond.trap(|_| xcc::Red).inside(|| {
|
||||
let t = SThunk { x : 10 };
|
||||
assert_eq!(xcc::callback(t), xcc::Red)
|
||||
})
|
||||
}
|
||||
|
|
@ -18,11 +18,4 @@ use other = xcrate_static_addresses;
|
|||
pub fn main() {
|
||||
other::verify_same(&other::global);
|
||||
other::verify_same2(other::global2);
|
||||
|
||||
// Previously this fail'd because there were two addresses that were being
|
||||
// used when declaring constants.
|
||||
other::test::cond.trap(|_| {
|
||||
}).inside(|| {
|
||||
other::raise();
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue