Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stabilize Result::as_deref and as_deref_mut #74948

Merged
merged 3 commits into from
Aug 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 2 additions & 26 deletions library/core/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,6 @@ impl<T, E: Into<!>> Result<T, E> {
}
}

#[unstable(feature = "inner_deref", issue = "50264")]
impl<T: Deref, E> Result<T, E> {
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&<T as Deref>::Target, &E>`.
///
Expand All @@ -1155,7 +1154,6 @@ impl<T: Deref, E> Result<T, E> {
/// # Examples
///
/// ```
/// #![feature(inner_deref)]
/// let x: Result<String, u32> = Ok("hello".to_string());
/// let y: Result<&str, &u32> = Ok("hello");
/// assert_eq!(x.as_deref(), y);
Expand All @@ -1164,23 +1162,12 @@ impl<T: Deref, E> Result<T, E> {
/// let y: Result<&str, &u32> = Err(&42);
/// assert_eq!(x.as_deref(), y);
/// ```
#[stable(feature = "inner_deref", since = "1.47.0")]
dtolnay marked this conversation as resolved.
Show resolved Hide resolved
pub fn as_deref(&self) -> Result<&T::Target, &E> {
self.as_ref().map(|t| t.deref())
}
}

#[unstable(feature = "inner_deref", issue = "50264")]
impl<T, E: Deref> Result<T, E> {
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T, &<E as Deref>::Target>`.
///
/// Coerces the [`Err`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref)
/// and returns the new [`Result`].
pub fn as_deref_err(&self) -> Result<&T, &E::Target> {
self.as_ref().map_err(|e| e.deref())
}
}

#[unstable(feature = "inner_deref", issue = "50264")]
impl<T: DerefMut, E> Result<T, E> {
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut <T as DerefMut>::Target, &mut E>`.
///
Expand All @@ -1190,7 +1177,6 @@ impl<T: DerefMut, E> Result<T, E> {
/// # Examples
///
/// ```
/// #![feature(inner_deref)]
/// let mut s = "HELLO".to_string();
/// let mut x: Result<String, u32> = Ok("hello".to_string());
/// let y: Result<&mut str, &mut u32> = Ok(&mut s);
Expand All @@ -1201,22 +1187,12 @@ impl<T: DerefMut, E> Result<T, E> {
/// let y: Result<&mut str, &mut u32> = Err(&mut i);
/// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
/// ```
#[stable(feature = "inner_deref", since = "1.47.0")]
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {
self.as_mut().map(|t| t.deref_mut())
}
}

#[unstable(feature = "inner_deref", issue = "50264")]
impl<T, E: DerefMut> Result<T, E> {
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T, &mut <E as DerefMut>::Target>`.
///
/// Coerces the [`Err`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut)
/// and returns the new [`Result`].
pub fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> {
self.as_mut().map_err(|e| e.deref_mut())
}
}

impl<T, E> Result<Option<T>, E> {
/// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
///
Expand Down
1 change: 0 additions & 1 deletion library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
#![feature(test)]
#![feature(trusted_len)]
#![feature(try_trait)]
#![feature(inner_deref)]
#![feature(slice_internals)]
#![feature(slice_partition_dedup)]
#![feature(int_error_matching)]
Expand Down
127 changes: 9 additions & 118 deletions library/core/tests/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,24 +250,11 @@ fn test_result_as_deref() {
let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice());
assert_eq!(ref_ok.as_deref(), expected_result);

// &Result<T, E: Deref>::Err(T).as_deref_err() ->
// Result<&T, &E::Deref::Target>::Err(&*E)
let ref_err = &Result::Err::<u8, &i32>(&41);
let expected_result = Result::Err::<&u8, &i32>(&41);
assert_eq!(ref_err.as_deref_err(), expected_result);

let ref_err = &Result::Err::<u32, String>(String::from("an error"));
let expected_result = Result::Err::<&u32, &str>("an error");
assert_eq!(ref_err.as_deref_err(), expected_result);

let ref_err = &Result::Err::<u32, Vec<i32>>(vec![5, 4, 3, 2, 1]);
let expected_result = Result::Err::<&u32, &[i32]>([5, 4, 3, 2, 1].as_slice());
assert_eq!(ref_err.as_deref_err(), expected_result);

// &Result<T: Deref, E: Deref>::Err(T).as_deref_err() ->
// Result<&T, &E::Deref::Target>::Err(&*E)
let ref_err = &Result::Err::<&u8, &i32>(&41);
let expected_result = Result::Err::<&u8, &&i32>(&&41);
// &Result<T: Deref, E>::Err(T).as_deref() ->
// Result<&T::Deref::Target, &E>::Err(&*E)
let val = 41;
let ref_err = &Result::Err::<&u8, i32>(val);
let expected_result = Result::Err::<&u8, &i32>(&val);
assert_eq!(ref_err.as_deref(), expected_result);

let s = String::from("an error");
Expand All @@ -279,46 +266,12 @@ fn test_result_as_deref() {
let ref_err = &Result::Err::<&u32, Vec<i32>>(v.clone());
let expected_result = Result::Err::<&u32, &Vec<i32>>(&v);
assert_eq!(ref_err.as_deref(), expected_result);

// The following cases test calling `as_deref_*` with the wrong variant (i.e.
// `as_deref()` with a `Result::Err()`, or `as_deref_err()` with a `Result::Ok()`.
// While uncommon, these cases are supported to ensure that an `as_deref_*`
// call can still be made even when one of the Result types does not implement
// `Deref` (for example, std::io::Error).

// &Result<T, E: Deref>::Ok(T).as_deref_err() ->
// Result<&T, &E::Deref::Target>::Ok(&T)
let ref_ok = &Result::Ok::<i32, &u8>(42);
let expected_result = Result::Ok::<&i32, &u8>(&42);
assert_eq!(ref_ok.as_deref_err(), expected_result);

let ref_ok = &Result::Ok::<&str, &u32>("a result");
let expected_result = Result::Ok::<&&str, &u32>(&"a result");
assert_eq!(ref_ok.as_deref_err(), expected_result);

let ref_ok = &Result::Ok::<[i32; 5], &u32>([1, 2, 3, 4, 5]);
let expected_result = Result::Ok::<&[i32; 5], &u32>(&[1, 2, 3, 4, 5]);
assert_eq!(ref_ok.as_deref_err(), expected_result);

// &Result<T: Deref, E>::Err(E).as_deref() ->
// Result<&T::Deref::Target, &E>::Err(&E)
let ref_err = &Result::Err::<&u8, i32>(41);
let expected_result = Result::Err::<&u8, &i32>(&41);
assert_eq!(ref_err.as_deref(), expected_result);

let ref_err = &Result::Err::<&u32, &str>("an error");
let expected_result = Result::Err::<&u32, &&str>(&"an error");
assert_eq!(ref_err.as_deref(), expected_result);

let ref_err = &Result::Err::<&u32, [i32; 5]>([5, 4, 3, 2, 1]);
let expected_result = Result::Err::<&u32, &[i32; 5]>(&[5, 4, 3, 2, 1]);
assert_eq!(ref_err.as_deref(), expected_result);
}

#[test]
fn test_result_as_deref_mut() {
// &mut Result<T: Deref, E>::Ok(T).as_deref_mut() ->
// Result<&mut T::Deref::Target, &mut E>::Ok(&mut *T)
// &mut Result<T: DerefMut, E>::Ok(T).as_deref_mut() ->
// Result<&mut T::DerefMut::Target, &mut E>::Ok(&mut *T)
let mut val = 42;
let mut expected_val = 42;
let mut_ok = &mut Result::Ok::<&mut i32, u8>(&mut val);
Expand All @@ -335,26 +288,8 @@ fn test_result_as_deref_mut() {
let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice());
assert_eq!(mut_ok.as_deref_mut(), expected_result);

// &mut Result<T, E: Deref>::Err(T).as_deref_mut_err() ->
// Result<&mut T, &mut E::Deref::Target>::Err(&mut *E)
let mut val = 41;
let mut expected_val = 41;
let mut_err = &mut Result::Err::<u8, &mut i32>(&mut val);
let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
assert_eq!(mut_err.as_deref_mut_err(), expected_result);

let mut expected_string = String::from("an error");
let mut_err = &mut Result::Err::<u32, String>(expected_string.clone());
let expected_result = Result::Err::<&mut u32, &mut str>(expected_string.deref_mut());
assert_eq!(mut_err.as_deref_mut_err(), expected_result);

let mut expected_vec = vec![5, 4, 3, 2, 1];
let mut_err = &mut Result::Err::<u32, Vec<i32>>(expected_vec.clone());
let expected_result = Result::Err::<&mut u32, &mut [i32]>(expected_vec.as_mut_slice());
assert_eq!(mut_err.as_deref_mut_err(), expected_result);

// &mut Result<T: Deref, E: Deref>::Err(T).as_deref_mut_err() ->
// Result<&mut T, &mut E::Deref::Target>::Err(&mut *E)
// &mut Result<T: DerefMut, E>::Err(T).as_deref_mut() ->
// Result<&mut T, &mut E>::Err(&mut *E)
let mut val = 41;
let mut_err = &mut Result::Err::<&mut u8, i32>(val);
let expected_result = Result::Err::<&mut u8, &mut i32>(&mut val);
Expand All @@ -369,48 +304,4 @@ fn test_result_as_deref_mut() {
let mut_err = &mut Result::Err::<&mut u32, Vec<i32>>(expected_vec.clone());
let expected_result = Result::Err::<&mut u32, &mut Vec<i32>>(&mut expected_vec);
assert_eq!(mut_err.as_deref_mut(), expected_result);

// The following cases test calling `as_deref_mut_*` with the wrong variant (i.e.
// `as_deref_mut()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`.
// While uncommon, these cases are supported to ensure that an `as_deref_mut_*`
// call can still be made even when one of the Result types does not implement
// `Deref` (for example, std::io::Error).

// &mut Result<T, E: Deref>::Ok(T).as_deref_mut_err() ->
// Result<&mut T, &mut E::Deref::Target>::Ok(&mut T)
let mut expected_val = 42;
let mut_ok = &mut Result::Ok::<i32, &mut u8>(expected_val.clone());
let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
assert_eq!(mut_ok.as_deref_mut_err(), expected_result);

let string = String::from("a result");
let expected_string = string.clone();
let mut ref_str = expected_string.as_ref();
let mut_ok = &mut Result::Ok::<&str, &mut u32>(string.as_str());
let expected_result = Result::Ok::<&mut &str, &mut u32>(&mut ref_str);
assert_eq!(mut_ok.as_deref_mut_err(), expected_result);

let mut expected_arr = [1, 2, 3, 4, 5];
let mut_ok = &mut Result::Ok::<[i32; 5], &mut u32>(expected_arr.clone());
let expected_result = Result::Ok::<&mut [i32; 5], &mut u32>(&mut expected_arr);
assert_eq!(mut_ok.as_deref_mut_err(), expected_result);

// &mut Result<T: Deref, E>::Err(E).as_deref_mut() ->
// Result<&mut T::Deref::Target, &mut E>::Err(&mut E)
let mut expected_val = 41;
let mut_err = &mut Result::Err::<&mut u8, i32>(expected_val.clone());
let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
assert_eq!(mut_err.as_deref_mut(), expected_result);

let string = String::from("an error");
let expected_string = string.clone();
let mut ref_str = expected_string.as_ref();
let mut_err = &mut Result::Err::<&mut u32, &str>(string.as_str());
let expected_result = Result::Err::<&mut u32, &mut &str>(&mut ref_str);
assert_eq!(mut_err.as_deref_mut(), expected_result);

let mut expected_arr = [5, 4, 3, 2, 1];
let mut_err = &mut Result::Err::<&mut u32, [i32; 5]>(expected_arr.clone());
let expected_result = Result::Err::<&mut u32, &mut [i32; 5]>(&mut expected_arr);
assert_eq!(mut_err.as_deref_mut(), expected_result);
}
1 change: 0 additions & 1 deletion library/proc_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#![feature(decl_macro)]
#![feature(extern_types)]
#![feature(in_band_lifetimes)]
#![feature(inner_deref)]
#![feature(negative_impls)]
#![feature(optin_builtin_traits)]
#![feature(restricted_std)]
Expand Down
1 change: 0 additions & 1 deletion src/librustc_builtin_macros/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#![feature(bool_to_option)]
#![feature(crate_visibility_modifier)]
#![feature(decl_macro)]
#![feature(inner_deref)]
#![feature(nll)]
#![feature(or_patterns)]
#![feature(proc_macro_internals)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![feature(inner_deref)]

fn main() {
let _result = &Ok(42).as_deref();
//~^ ERROR no method named `as_deref` found
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
error[E0599]: no method named `as_deref` found for enum `std::result::Result<{integer}, _>` in the current scope
--> $DIR/result-as_deref.rs:4:27
--> $DIR/result-as_deref.rs:2:27
|
LL | let _result = &Ok(42).as_deref();
| ^^^^^^^^ help: there is an associated function with a similar name: `as_ref`
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![feature(inner_deref)]

fn main() {
let _result = &mut Ok(42).as_deref_mut();
//~^ ERROR no method named `as_deref_mut` found
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0599]: no method named `as_deref_mut` found for enum `std::result::Result<{integer}, _>` in the current scope
--> $DIR/result-as_deref_mut.rs:4:31
--> $DIR/result-as_deref_mut.rs:2:31
|
LL | let _result = &mut Ok(42).as_deref_mut();
| ^^^^^^^^^^^^ help: there is an associated function with a similar name: `as_deref_err`
| ^^^^^^^^^^^^ method not found in `std::result::Result<{integer}, _>`
|
= note: the method `as_deref_mut` exists but the following trait bounds were not satisfied:
`{integer}: std::ops::DerefMut`
Expand Down

This file was deleted.

This file was deleted.