Skip to content

Commit e1fb2b7

Browse files
committed
added deref_mut_* versions of inner_deref methods as per discussion #50264
1 parent 25e4447 commit e1fb2b7

16 files changed

+274
-14
lines changed

src/libcore/option.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@
136136
#![stable(feature = "rust1", since = "1.0.0")]
137137

138138
use iter::{FromIterator, FusedIterator, TrustedLen};
139-
use {hint, mem, ops::{self, Deref}};
139+
use {hint, mem, ops::{self, Deref, DerefMut}};
140140
use pin::Pin;
141141

142142
// Note that this is not a lang item per se, but it has a hidden dependency on
@@ -1000,6 +1000,17 @@ impl<T: Deref> Option<T> {
10001000
}
10011001
}
10021002

1003+
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
1004+
impl<T: DerefMut> Option<T> {
1005+
/// Converts from `Option<T>` (or `&mut Option<T>`) to `Option<&mut T::Target>`.
1006+
///
1007+
/// Leaves the original `Option` in-place, creating a new one containing a mutable reference to
1008+
/// the inner type's `Deref::Target` type.
1009+
pub fn as_deref_mut(&mut self) -> Option<&mut T::Target> {
1010+
self.as_mut().map(|t| t.deref_mut())
1011+
}
1012+
}
1013+
10031014
impl<T, E> Option<Result<T, E>> {
10041015
/// Transposes an `Option` of a `Result` into a `Result` of an `Option`.
10051016
///

src/libcore/result.rs

+40-4
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@
232232

233233
use fmt;
234234
use iter::{FromIterator, FusedIterator, TrustedLen};
235-
use ops::{self, Deref};
235+
use ops::{self, Deref, DerefMut};
236236

237237
/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
238238
///
@@ -927,7 +927,7 @@ impl<T: Default, E> Result<T, E> {
927927

928928
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
929929
impl<T: Deref, E> Result<T, E> {
930-
/// Converts from `&Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E>`.
930+
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E>`.
931931
///
932932
/// Leaves the original `Result` in-place, creating a new one containing a reference to the
933933
/// `Ok` type's `Deref::Target` type.
@@ -938,7 +938,7 @@ impl<T: Deref, E> Result<T, E> {
938938

939939
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
940940
impl<T, E: Deref> Result<T, E> {
941-
/// Converts from `&Result<T, E>` (or `&Result<T, E>`) to `Result<&T, &E::Target>`.
941+
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T, &E::Target>`.
942942
///
943943
/// Leaves the original `Result` in-place, creating a new one containing a reference to the
944944
/// `Err` type's `Deref::Target` type.
@@ -950,7 +950,7 @@ impl<T, E: Deref> Result<T, E> {
950950

951951
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
952952
impl<T: Deref, E: Deref> Result<T, E> {
953-
/// Converts from `&Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E::Target>`.
953+
/// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E::Target>`.
954954
///
955955
/// Leaves the original `Result` in-place, creating a new one containing a reference to both
956956
/// the `Ok` and `Err` types' `Deref::Target` types.
@@ -960,6 +960,42 @@ impl<T: Deref, E: Deref> Result<T, E> {
960960
}
961961
}
962962

963+
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
964+
impl<T: DerefMut, E> Result<T, E> {
965+
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T::Target, &mut E>`.
966+
///
967+
/// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
968+
/// the `Ok` type's `Deref::Target` type.
969+
pub fn as_deref_mut_ok(&mut self) -> Result<&mut T::Target, &mut E> {
970+
self.as_mut().map(|t| t.deref_mut())
971+
}
972+
}
973+
974+
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
975+
impl<T, E: DerefMut> Result<T, E> {
976+
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T, &mut E::Target>`.
977+
///
978+
/// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
979+
/// the `Err` type's `Deref::Target` type.
980+
pub fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target>
981+
{
982+
self.as_mut().map_err(|e| e.deref_mut())
983+
}
984+
}
985+
986+
#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
987+
impl<T: DerefMut, E: DerefMut> Result<T, E> {
988+
/// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to
989+
/// `Result<&mut T::Target, &mut E::Target>`.
990+
///
991+
/// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
992+
/// both the `Ok` and `Err` types' `Deref::Target` types.
993+
pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E::Target>
994+
{
995+
self.as_mut().map(|t| t.deref_mut()).map_err(|e| e.deref_mut())
996+
}
997+
}
998+
963999
impl<T, E> Result<Option<T>, E> {
9641000
/// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
9651001
///

src/libcore/tests/option.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use core::option::*;
22
use core::mem;
33
use core::clone::Clone;
4+
use core::array::FixedSizeArray;
5+
use core::ops::DerefMut;
46

57
#[test]
68
fn test_get_ptr() {
@@ -319,13 +321,31 @@ fn test_option_as_deref() {
319321
assert_eq!(ref_option.as_deref(), Some("a result"));
320322

321323
let ref_option = &Some(vec![1, 2, 3, 4, 5]);
322-
assert_eq!(ref_option.as_deref(), Some(&[1, 2, 3, 4, 5][..]));
324+
assert_eq!(ref_option.as_deref(), Some([1, 2, 3, 4, 5].as_slice()));
323325

324326
// None: &Option<T: Deref>>::None -> None
325327
let ref_option: &Option<&i32> = &None;
326328
assert_eq!(ref_option.as_deref(), None);
327329
}
328330

331+
#[test]
332+
fn test_option_as_deref_mut() {
333+
// Some: &mut Option<T: Deref>::Some(T) -> Option<&mut T::Deref::Target>::Some(&mut *T)
334+
let mut val = 42;
335+
let ref_option = &mut Some(&mut val);
336+
assert_eq!(ref_option.as_deref_mut(), Some(&mut 42));
337+
338+
let ref_option = &mut Some(String::from("a result"));
339+
assert_eq!(ref_option.as_deref_mut(), Some(String::from("a result").deref_mut()));
340+
341+
let ref_option = &mut Some(vec![1, 2, 3, 4, 5]);
342+
assert_eq!(ref_option.as_deref_mut(), Some([1, 2, 3, 4, 5].as_mut_slice()));
343+
344+
// None: &mut Option<T: Deref>>::None -> None
345+
let ref_option: &mut Option<&mut i32> = &mut None;
346+
assert_eq!(ref_option.as_deref_mut(), None);
347+
}
348+
329349
#[test]
330350
fn test_replace() {
331351
let mut x = Some(2);

src/libcore/tests/result.rs

+125-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
use core::option::*;
2+
use core::array::FixedSizeArray;
3+
use core::ops::DerefMut;
24

35
fn op1() -> Result<isize, &'static str> { Ok(666) }
46
fn op2() -> Result<isize, &'static str> { Err("sadface") }
@@ -237,7 +239,7 @@ fn test_result_as_deref() {
237239
assert_eq!(ref_ok.as_deref_ok(), expected_result);
238240

239241
let ref_ok = &Result::Ok::<Vec<i32>, u32>(vec![1, 2, 3, 4, 5]);
240-
let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]);
242+
let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice());
241243
assert_eq!(ref_ok.as_deref_ok(), expected_result);
242244

243245
// &Result<T: Deref, E: Deref>::Ok(T).as_deref() ->
@@ -251,7 +253,7 @@ fn test_result_as_deref() {
251253
assert_eq!(ref_ok.as_deref(), expected_result);
252254

253255
let ref_ok = &Result::Ok::<Vec<i32>, &u32>(vec![1, 2, 3, 4, 5]);
254-
let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]);
256+
let expected_result = Result::Ok::<&[i32], &u32>([1, 2, 3, 4, 5].as_slice());
255257
assert_eq!(ref_ok.as_deref(), expected_result);
256258

257259
// &Result<T, E: Deref>::Err(T).as_deref_err() ->
@@ -265,7 +267,7 @@ fn test_result_as_deref() {
265267
assert_eq!(ref_err.as_deref_err(), expected_result);
266268

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

271273
// &Result<T: Deref, E: Deref>::Err(T).as_deref_err() ->
@@ -279,7 +281,7 @@ fn test_result_as_deref() {
279281
assert_eq!(ref_err.as_deref(), expected_result);
280282

281283
let ref_err = &Result::Err::<&u32, Vec<i32>>(vec![5, 4, 3, 2, 1]);
282-
let expected_result = Result::Err::<&u32, &[i32]>(&[5, 4, 3, 2, 1][..]);
284+
let expected_result = Result::Err::<&u32, &[i32]>([5, 4, 3, 2, 1].as_slice());
283285
assert_eq!(ref_err.as_deref(), expected_result);
284286

285287
// The following cases test calling `as_deref_*` with the wrong variant (i.e.
@@ -316,3 +318,122 @@ fn test_result_as_deref() {
316318
let expected_result = Result::Err::<&u32, &[i32; 5]>(&[5, 4, 3, 2, 1]);
317319
assert_eq!(ref_err.as_deref_ok(), expected_result);
318320
}
321+
322+
#[test]
323+
fn test_result_as_deref_mut() {
324+
// &mut Result<T: Deref, E>::Ok(T).as_deref_mut_ok() ->
325+
// Result<&mut T::Deref::Target, &mut E>::Ok(&mut *T)
326+
let mut val = 42;
327+
let mut expected_val = 42;
328+
let mut_ok = &mut Result::Ok::<&mut i32, u8>(&mut val);
329+
let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
330+
assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
331+
332+
let mut expected_string = String::from("a result");
333+
let mut_ok = &mut Result::Ok::<String, u32>(expected_string.clone());
334+
let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut());
335+
assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
336+
337+
let mut expected_vec = vec![1, 2, 3, 4, 5];
338+
let mut_ok = &mut Result::Ok::<Vec<i32>, u32>(expected_vec.clone());
339+
let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice());
340+
assert_eq!(mut_ok.as_deref_mut_ok(), expected_result);
341+
342+
// &mut Result<T: Deref, E: Deref>::Ok(T).as_deref_mut() ->
343+
// Result<&mut T::Deref::Target, &mut E::Deref::Target>::Ok(&mut *T)
344+
let mut val = 42;
345+
let mut expected_val = 42;
346+
let mut_ok = &mut Result::Ok::<&mut i32, &mut u8>(&mut val);
347+
let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
348+
assert_eq!(mut_ok.as_deref_mut(), expected_result);
349+
350+
let mut expected_string = String::from("a result");
351+
let mut_ok = &mut Result::Ok::<String, &mut u32>(expected_string.clone());
352+
let expected_result = Result::Ok::<&mut str, &mut u32>(expected_string.deref_mut());
353+
assert_eq!(mut_ok.as_deref_mut(), expected_result);
354+
355+
let mut expected_vec = vec![1, 2, 3, 4, 5];
356+
let mut_ok = &mut Result::Ok::<Vec<i32>, &mut u32>(expected_vec.clone());
357+
let expected_result = Result::Ok::<&mut [i32], &mut u32>(expected_vec.as_mut_slice());
358+
assert_eq!(mut_ok.as_deref_mut(), expected_result);
359+
360+
// &mut Result<T, E: Deref>::Err(T).as_deref_mut_err() ->
361+
// Result<&mut T, &mut E::Deref::Target>::Err(&mut *E)
362+
let mut val = 41;
363+
let mut expected_val = 41;
364+
let mut_err = &mut Result::Err::<u8, &mut i32>(&mut val);
365+
let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
366+
assert_eq!(mut_err.as_deref_mut_err(), expected_result);
367+
368+
let mut expected_string = String::from("an error");
369+
let mut_err = &mut Result::Err::<u32, String>(expected_string.clone());
370+
let expected_result = Result::Err::<&mut u32, &mut str>(expected_string.deref_mut());
371+
assert_eq!(mut_err.as_deref_mut_err(), expected_result);
372+
373+
let mut expected_vec = vec![5, 4, 3, 2, 1];
374+
let mut_err = &mut Result::Err::<u32, Vec<i32>>(expected_vec.clone());
375+
let expected_result = Result::Err::<&mut u32, &mut [i32]>(expected_vec.as_mut_slice());
376+
assert_eq!(mut_err.as_deref_mut_err(), expected_result);
377+
378+
// &mut Result<T: Deref, E: Deref>::Err(T).as_deref_mut_err() ->
379+
// Result<&mut T, &mut E::Deref::Target>::Err(&mut *E)
380+
let mut val = 41;
381+
let mut expected_val = 41;
382+
let mut_err = &mut Result::Err::<&mut u8, &mut i32>(&mut val);
383+
let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
384+
assert_eq!(mut_err.as_deref_mut(), expected_result);
385+
386+
let mut expected_string = String::from("an error");
387+
let mut_err = &mut Result::Err::<&mut u32, String>(expected_string.clone());
388+
let expected_result = Result::Err::<&mut u32, &mut str>(expected_string.as_mut_str());
389+
assert_eq!(mut_err.as_deref_mut(), expected_result);
390+
391+
let mut expected_vec = vec![5, 4, 3, 2, 1];
392+
let mut_err = &mut Result::Err::<&mut u32, Vec<i32>>(expected_vec.clone());
393+
let expected_result = Result::Err::<&mut u32, &mut [i32]>(expected_vec.as_mut_slice());
394+
assert_eq!(mut_err.as_deref_mut(), expected_result);
395+
396+
// The following cases test calling `as_deref_mut_*` with the wrong variant (i.e.
397+
// `as_deref_mut_ok()` with a `Result::Err()`, or `as_deref_mut_err()` with a `Result::Ok()`.
398+
// While uncommon, these cases are supported to ensure that an `as_deref_mut_*`
399+
// call can still be made even when one of the Result types does not implement
400+
// `Deref` (for example, std::io::Error).
401+
402+
// &mut Result<T, E: Deref>::Ok(T).as_deref_mut_err() ->
403+
// Result<&mut T, &mut E::Deref::Target>::Ok(&mut T)
404+
let mut expected_val = 42;
405+
let mut_ok = &mut Result::Ok::<i32, &mut u8>(expected_val.clone());
406+
let expected_result = Result::Ok::<&mut i32, &mut u8>(&mut expected_val);
407+
assert_eq!(mut_ok.as_deref_mut_err(), expected_result);
408+
409+
let string = String::from("a result");
410+
let expected_string = string.clone();
411+
let mut ref_str = expected_string.as_ref();
412+
let mut_ok = &mut Result::Ok::<&str, &mut u32>(string.as_str());
413+
let expected_result = Result::Ok::<&mut &str, &mut u32>(&mut ref_str);
414+
assert_eq!(mut_ok.as_deref_mut_err(), expected_result);
415+
416+
let mut expected_arr = [1, 2, 3, 4, 5];
417+
let mut_ok = &mut Result::Ok::<[i32; 5], &mut u32>(expected_arr.clone());
418+
let expected_result = Result::Ok::<&mut [i32; 5], &mut u32>(&mut expected_arr);
419+
assert_eq!(mut_ok.as_deref_mut_err(), expected_result);
420+
421+
// &mut Result<T: Deref, E>::Err(E).as_deref_mut_ok() ->
422+
// Result<&mut T::Deref::Target, &mut E>::Err(&mut E)
423+
let mut expected_val = 41;
424+
let mut_err = &mut Result::Err::<&mut u8, i32>(expected_val.clone());
425+
let expected_result = Result::Err::<&mut u8, &mut i32>(&mut expected_val);
426+
assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
427+
428+
let string = String::from("an error");
429+
let expected_string = string.clone();
430+
let mut ref_str = expected_string.as_ref();
431+
let mut_err = &mut Result::Err::<&mut u32, &str>(string.as_str());
432+
let expected_result = Result::Err::<&mut u32, &mut &str>(&mut ref_str);
433+
assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
434+
435+
let mut expected_arr = [5, 4, 3, 2, 1];
436+
let mut_err = &mut Result::Err::<&mut u32, [i32; 5]>(expected_arr.clone());
437+
let expected_result = Result::Err::<&mut u32, &mut [i32; 5]>(&mut expected_arr);
438+
assert_eq!(mut_err.as_deref_mut_ok(), expected_result);
439+
}

src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for type `std::option::Option<{in
22
--> $DIR/option-as_deref.rs:4:29
33
|
44
LL | let _result = &Some(42).as_deref();
5-
| ^^^^^^^^
5+
| ^^^^^^^^ help: did you mean: `as_ref`
66
|
77
= note: the method `as_deref` exists but the following trait bounds were not satisfied:
88
`{integer} : std::ops::Deref`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(inner_deref)]
2+
3+
fn main() {
4+
let _result = &mut Some(42).as_deref_mut();
5+
//~^ ERROR no method named `as_deref_mut` found for type `std::option::Option<{integer}>`
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0599]: no method named `as_deref_mut` found for type `std::option::Option<{integer}>` in the current scope
2+
--> $DIR/option-as_deref_mut.rs:4:33
3+
|
4+
LL | let _result = &mut Some(42).as_deref_mut();
5+
| ^^^^^^^^^^^^
6+
|
7+
= note: the method `as_deref_mut` exists but the following trait bounds were not satisfied:
8+
`{integer} : std::ops::DerefMut`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0599`.

src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref` found for type `std::result::Result<{in
22
--> $DIR/result-as_deref.rs:4:27
33
|
44
LL | let _result = &Ok(42).as_deref();
5-
| ^^^^^^^^
5+
| ^^^^^^^^ help: did you mean: `as_ref`
66
|
77
= note: the method `as_deref` exists but the following trait bounds were not satisfied:
88
`{integer} : std::ops::Deref`

src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error[E0599]: no method named `as_deref_err` found for type `std::result::Result
22
--> $DIR/result-as_deref_err.rs:4:28
33
|
44
LL | let _result = &Err(41).as_deref_err();
5-
| ^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^ help: did you mean: `as_deref_ok`
66
|
77
= note: the method `as_deref_err` exists but the following trait bounds were not satisfied:
88
`{integer} : std::ops::Deref`
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(inner_deref)]
2+
3+
fn main() {
4+
let _result = &mut Ok(42).as_deref_mut();
5+
//~^ ERROR no method named `as_deref_mut` found
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0599]: no method named `as_deref_mut` found for type `std::result::Result<{integer}, _>` in the current scope
2+
--> $DIR/result-as_deref_mut.rs:4:31
3+
|
4+
LL | let _result = &mut Ok(42).as_deref_mut();
5+
| ^^^^^^^^^^^^ help: did you mean: `as_deref_err`
6+
|
7+
= note: the method `as_deref_mut` exists but the following trait bounds were not satisfied:
8+
`{integer} : std::ops::DerefMut`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0599`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(inner_deref)]
2+
3+
fn main() {
4+
let _result = &mut Err(41).as_deref_mut_err();
5+
//~^ ERROR no method named `as_deref_mut_err` found
6+
}

0 commit comments

Comments
 (0)