Skip to content

Commit 4c2e314

Browse files
committed
added DerefOption and DerefResult + tests to std
1 parent 7f3444e commit 4c2e314

File tree

4 files changed

+109
-3
lines changed

4 files changed

+109
-3
lines changed

src/libcore/option.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@
146146
#![stable(feature = "rust1", since = "1.0.0")]
147147

148148
use iter::{FromIterator, FusedIterator, TrustedLen};
149-
use {mem, ops};
149+
use {mem, ops::{self, Deref}};
150150

151151
// Note that this is not a lang item per se, but it has a hidden dependency on
152152
// `Iterator`, which is one. The compiler assumes that the `next` method of
@@ -914,7 +914,6 @@ fn expect_failed(msg: &str) -> ! {
914914
panic!("{}", msg)
915915
}
916916

917-
918917
/////////////////////////////////////////////////////////////////////////////
919918
// Trait implementations
920919
/////////////////////////////////////////////////////////////////////////////
@@ -979,6 +978,24 @@ impl<T> From<T> for Option<T> {
979978
}
980979
}
981980

981+
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
982+
/// Extension trait to get a reference of an Option via the Deref trait.
983+
pub trait OptionDeref<T: Deref> {
984+
/// Converts from `&Option<T>` to `Option<&T::Target>`.
985+
///
986+
/// Leaves the original Option in-place, creating a new one with a reference
987+
/// to the original one, additionally coercing the contents via `Deref`.
988+
fn deref(&self) -> Option<&T::Target>;
989+
}
990+
991+
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
992+
impl<T: Deref> OptionDeref<T> for Option<T>
993+
{
994+
fn deref(&self) -> Option<&T::Target> {
995+
self.as_ref().map(|t| t.deref())
996+
}
997+
}
998+
982999
/////////////////////////////////////////////////////////////////////////////
9831000
// The Option Iterators
9841001
/////////////////////////////////////////////////////////////////////////////

src/libcore/result.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@
242242

243243
use fmt;
244244
use iter::{FromIterator, FusedIterator, TrustedLen};
245-
use ops;
245+
use ops::{self, Deref};
246246

247247
/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
248248
///
@@ -999,6 +999,63 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
999999
}
10001000
}
10011001

1002+
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
1003+
/// Extension trait to get a reference to a Result via the Deref trait.
1004+
pub trait ResultDeref<T, E> {
1005+
/// Converts from `&Result<T, E>` to `Result<&T::Target, &E>`.
1006+
///
1007+
/// Leaves the original Result in-place, creating a new one with a reference
1008+
/// to the original one, additionally coercing the `Ok` arm of the Result via
1009+
/// `Deref`.
1010+
fn deref_ok(&self) -> Result<&T::Target, &E>
1011+
where
1012+
T: Deref;
1013+
1014+
/// Converts from `&Result<T, E>` to `Result<&T, &E::Target>`.
1015+
///
1016+
/// Leaves the original Result in-place, creating a new one with a reference
1017+
/// to the original one, additionally coercing the `Err` arm of the Result via
1018+
/// `Deref`.
1019+
fn deref_err(&self) -> Result<&T, &E::Target>
1020+
where
1021+
E: Deref;
1022+
1023+
/// Converts from `&Result<T, E>` to `Result<&T::Target, &E::Target>`.
1024+
///
1025+
/// Leaves the original Result in-place, creating a new one with a reference
1026+
/// to the original one, additionally coercing both the `Ok` and `Err` arms
1027+
/// of the Result via `Deref`.
1028+
fn deref(&self) -> Result<&T::Target, &E::Target>
1029+
where
1030+
T: Deref,
1031+
E: Deref;
1032+
}
1033+
1034+
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
1035+
impl<T, E> ResultDeref<T, E> for Result<T, E> {
1036+
fn deref_ok(&self) -> Result<&T::Target, &E>
1037+
where
1038+
T: Deref,
1039+
{
1040+
self.as_ref().map(|t| t.deref())
1041+
}
1042+
1043+
fn deref_err(&self) -> Result<&T, &E::Target>
1044+
where
1045+
E: Deref,
1046+
{
1047+
self.as_ref().map_err(|e| e.deref())
1048+
}
1049+
1050+
fn deref(&self) -> Result<&T::Target, &E::Target>
1051+
where
1052+
T: Deref,
1053+
E: Deref,
1054+
{
1055+
self.as_ref().map(|t| t.deref()).map_err(|e| e.deref())
1056+
}
1057+
}
1058+
10021059
/////////////////////////////////////////////////////////////////////////////
10031060
// The Result Iterators
10041061
/////////////////////////////////////////////////////////////////////////////

src/libcore/tests/option.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,3 +297,14 @@ fn test_try() {
297297
}
298298
assert_eq!(try_option_err(), Err(NoneError));
299299
}
300+
301+
#[test]
302+
fn test_option_deref() {
303+
// Some: &Option<T: Deref>::Some(T) -> Option<&T::Deref::Target>::Some(&*T)
304+
let ref_option = &Some(&42);
305+
assert_eq!(ref_option.deref(), Some(&42));
306+
307+
// None: &Option<T: Deref>>::None -> None
308+
let ref_option = &None;
309+
assert_eq!(ref_option.deref(), None);
310+
}

src/libcore/tests/result.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,24 @@ fn test_try() {
231231
}
232232
assert_eq!(try_result_err(), Err(1));
233233
}
234+
235+
#[test]
236+
fn test_result_deref() {
237+
// Ok(T).deref_ok() -> Result<&T, &E::Deref::Target>::Ok(&T)
238+
let ref_ok: &Result<&i32, &u8> = &Ok(&42);
239+
assert_eq!(ref_ok.deref_ok(), Ok(&42));
240+
assert_eq!(ref_ok.deref_ok(), Ok(&42));
241+
assert_eq!(ref_ok.deref(), Ok(&42));
242+
243+
// Err(E) -> Result<&T, &E::Deref::Target>::Err(&*E)
244+
let ref_err: &Result<&i32, &u8> = &Err(&41);
245+
assert_eq!(ref_err.deref_err(), Err(&41));
246+
assert_eq!(ref_err.deref_err(), Err(&41));
247+
assert_eq!(ref_err.deref(), Err(&41));
248+
249+
// &Ok(T).deref_err() -> Result<&T, &E::Deref::Target>::Ok(&T)
250+
assert_eq!(ref_ok.deref_err(), Ok(&&42));
251+
252+
// &Err(E) -> Result<&T::Deref::Target, &E>::Err(&E)
253+
assert_eq!(ref_err.deref_ok(), Err(&&41));
254+
}

0 commit comments

Comments
 (0)