diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 84fa8ec35447..bb5cca90cd09 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -23,7 +23,7 @@ pure fn get(opt: option) -> T { * Fails if the value equals `none` */ - alt opt { some(x) { return x; } none { fail ~"option none"; } } + alt opt { some(x) { return x; } none { fail ~"option::get none"; } } } pure fn expect(opt: option, reason: ~str) -> T { @@ -112,7 +112,7 @@ pure fn unwrap(-opt: option) -> T { unsafe { let addr = alt opt { some(x) { ptr::addr_of(x) } - none { fail ~"option none" } + none { fail ~"option::unwrap none" } }; let liberated_value = unsafe::reinterpret_cast(*addr); unsafe::forget(opt); @@ -120,6 +120,13 @@ pure fn unwrap(-opt: option) -> T { } } +/// The ubiquitous option dance. +#[inline(always)] +fn swap_unwrap(opt: &mut option) -> T { + if opt.is_none() { fail ~"option::swap_unwrap none" } + unwrap(util::replace(opt, none)) +} + pure fn unwrap_expect(-opt: option, reason: ~str) -> T { //! As unwrap, but with a specified failure message. if opt.is_none() { fail reason; } @@ -204,6 +211,24 @@ fn test_unwrap_resource() { assert *i == 1; } +#[test] +fn test_option_dance() { + let x = some(()); + let mut y = some(5); + let mut y2 = 0; + do x.iter |_x| { + y2 = swap_unwrap(&mut y); + } + assert y2 == 5; + assert y.is_none(); +} +#[test] #[should_fail] #[ignore(cfg(windows))] +fn test_option_too_much_dance() { + let mut y = some(util::noncopyable()); + let _y2 = swap_unwrap(&mut y); + let _y3 = swap_unwrap(&mut y); +} + #[test] fn test_option_while_some() { let mut i = 0; diff --git a/src/libcore/util.rs b/src/libcore/util.rs index 9321f6d242b6..9b7a644b508b 100644 --- a/src/libcore/util.rs +++ b/src/libcore/util.rs @@ -9,6 +9,7 @@ pure fn id(+x: T) -> T { x } * Swap the values at two mutable locations of the same type, without * deinitialising or copying either one. */ +#[inline(always)] fn swap(x: &mut T, y: &mut T) { *x <-> *y; } @@ -17,6 +18,7 @@ fn swap(x: &mut T, y: &mut T) { * Replace the value at a mutable location with a new one, returning the old * value, without deinitialising or copying either one. */ +#[inline(always)] fn replace(dest: &mut T, +src: T) -> T { let mut tmp = src; swap(dest, &mut tmp);