From 4c2e3144a98f7a636fd6a33fce122121431ad9b4 Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Thu, 26 Apr 2018 16:29:22 -0700
Subject: [PATCH 1/9] added DerefOption and DerefResult + tests to std

---
 src/libcore/option.rs       | 21 +++++++++++--
 src/libcore/result.rs       | 59 ++++++++++++++++++++++++++++++++++++-
 src/libcore/tests/option.rs | 11 +++++++
 src/libcore/tests/result.rs | 21 +++++++++++++
 4 files changed, 109 insertions(+), 3 deletions(-)

diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 0dfdabee03182..c3ef619d739c0 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -146,7 +146,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use iter::{FromIterator, FusedIterator, TrustedLen};
-use {mem, ops};
+use {mem, ops::{self, Deref}};
 
 // Note that this is not a lang item per se, but it has a hidden dependency on
 // `Iterator`, which is one. The compiler assumes that the `next` method of
@@ -914,7 +914,6 @@ fn expect_failed(msg: &str) -> ! {
     panic!("{}", msg)
 }
 
-
 /////////////////////////////////////////////////////////////////////////////
 // Trait implementations
 /////////////////////////////////////////////////////////////////////////////
@@ -979,6 +978,24 @@ impl<T> From<T> for Option<T> {
     }
 }
 
+#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+/// Extension trait to get a reference of an Option via the Deref trait.
+pub trait OptionDeref<T: Deref> {
+    /// Converts from `&Option<T>` to `Option<&T::Target>`.
+    ///
+    /// Leaves the original Option in-place, creating a new one with a reference
+    /// to the original one, additionally coercing the contents via `Deref`.
+    fn deref(&self) -> Option<&T::Target>;
+}
+
+#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+impl<T: Deref> OptionDeref<T> for Option<T>
+{
+    fn deref(&self) -> Option<&T::Target> {
+        self.as_ref().map(|t| t.deref())
+    }
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // The Option Iterators
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index c152d4979b90e..9877a2001a0ff 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -242,7 +242,7 @@
 
 use fmt;
 use iter::{FromIterator, FusedIterator, TrustedLen};
-use ops;
+use ops::{self, Deref};
 
 /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
 ///
@@ -999,6 +999,63 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
     }
 }
 
+#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+/// Extension trait to get a reference to a Result via the Deref trait.
+pub trait ResultDeref<T, E> {
+    /// Converts from `&Result<T, E>` to `Result<&T::Target, &E>`.
+    ///
+    /// Leaves the original Result in-place, creating a new one with a reference
+    /// to the original one, additionally coercing the `Ok` arm of the Result via
+    /// `Deref`.
+    fn deref_ok(&self) -> Result<&T::Target, &E>
+                where
+                       T: Deref;
+
+    /// Converts from `&Result<T, E>` to `Result<&T, &E::Target>`.
+    ///
+    /// Leaves the original Result in-place, creating a new one with a reference
+    /// to the original one, additionally coercing the `Err` arm of the Result via
+    /// `Deref`.
+    fn deref_err(&self) -> Result<&T, &E::Target>
+                 where
+                        E: Deref;
+
+    /// Converts from `&Result<T, E>` to `Result<&T::Target, &E::Target>`.
+    ///
+    /// Leaves the original Result in-place, creating a new one with a reference
+    /// to the original one, additionally coercing both the `Ok` and `Err` arms
+    /// of the Result via `Deref`.
+    fn deref(&self) -> Result<&T::Target, &E::Target>
+             where
+                    T: Deref,
+                    E: Deref;
+}
+
+#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+impl<T, E> ResultDeref<T, E> for Result<T, E> {
+    fn deref_ok(&self) -> Result<&T::Target, &E>
+                where
+                       T: Deref,
+    {
+        self.as_ref().map(|t| t.deref())
+    }
+
+    fn deref_err(&self) -> Result<&T, &E::Target>
+                 where
+                        E: Deref,
+    {
+        self.as_ref().map_err(|e| e.deref())
+    }
+
+    fn deref(&self) -> Result<&T::Target, &E::Target>
+             where
+                    T: Deref,
+                    E: Deref,
+    {
+        self.as_ref().map(|t| t.deref()).map_err(|e| e.deref())
+    }
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // The Result Iterators
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index 22109e28edd9b..77d550c532a34 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -297,3 +297,14 @@ fn test_try() {
     }
     assert_eq!(try_option_err(), Err(NoneError));
 }
+
+#[test]
+fn test_option_deref() {
+    // Some: &Option<T: Deref>::Some(T) -> Option<&T::Deref::Target>::Some(&*T)
+    let ref_option = &Some(&42);
+    assert_eq!(ref_option.deref(), Some(&42));
+
+    // None: &Option<T: Deref>>::None -> None
+    let ref_option = &None;
+    assert_eq!(ref_option.deref(), None);
+}
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index ce41bde8342ed..dd23467322dc9 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -231,3 +231,24 @@ fn test_try() {
     }
     assert_eq!(try_result_err(), Err(1));
 }
+
+#[test]
+fn test_result_deref() {
+    // Ok(T).deref_ok() -> Result<&T, &E::Deref::Target>::Ok(&T)
+    let ref_ok: &Result<&i32, &u8> = &Ok(&42);
+    assert_eq!(ref_ok.deref_ok(), Ok(&42));
+    assert_eq!(ref_ok.deref_ok(), Ok(&42));
+    assert_eq!(ref_ok.deref(), Ok(&42));
+
+    // Err(E) -> Result<&T, &E::Deref::Target>::Err(&*E)
+    let ref_err: &Result<&i32, &u8> = &Err(&41);
+    assert_eq!(ref_err.deref_err(), Err(&41));
+    assert_eq!(ref_err.deref_err(), Err(&41));
+    assert_eq!(ref_err.deref(), Err(&41));
+
+    // &Ok(T).deref_err() -> Result<&T, &E::Deref::Target>::Ok(&T)
+    assert_eq!(ref_ok.deref_err(), Ok(&&42));
+
+    // &Err(E) -> Result<&T::Deref::Target, &E>::Err(&E)
+    assert_eq!(ref_err.deref_ok(), Err(&&41));
+}

From 6c7ea4ca9b92e527873115951cfc8c864bbb71ad Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Thu, 26 Apr 2018 19:54:24 -0700
Subject: [PATCH 2/9] refactored to implement without trait

---
 src/libcore/option.rs | 29 ++++++--------
 src/libcore/result.rs | 91 ++++++++++++++++---------------------------
 2 files changed, 45 insertions(+), 75 deletions(-)

diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index c3ef619d739c0..506e54ba5e4e6 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -878,6 +878,17 @@ impl<T: Default> Option<T> {
     }
 }
 
+# [unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+impl<T: Deref> Option<T> {
+    /// Converts from `&Option<T>` to `Option<&T::Target>`.
+    ///
+    /// Leaves the original Option in-place, creating a new one with a reference
+    /// to the original one, additionally coercing the contents via `Deref`.
+    pub fn deref(&self) -> Option<&T::Target> {
+        self.as_ref().map(|t| t.deref())
+    }
+}
+
 impl<T, E> Option<Result<T, E>> {
     /// Transposes an `Option` of a `Result` into a `Result` of an `Option`.
     ///
@@ -978,24 +989,6 @@ impl<T> From<T> for Option<T> {
     }
 }
 
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-/// Extension trait to get a reference of an Option via the Deref trait.
-pub trait OptionDeref<T: Deref> {
-    /// Converts from `&Option<T>` to `Option<&T::Target>`.
-    ///
-    /// Leaves the original Option in-place, creating a new one with a reference
-    /// to the original one, additionally coercing the contents via `Deref`.
-    fn deref(&self) -> Option<&T::Target>;
-}
-
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-impl<T: Deref> OptionDeref<T> for Option<T>
-{
-    fn deref(&self) -> Option<&T::Target> {
-        self.as_ref().map(|t| t.deref())
-    }
-}
-
 /////////////////////////////////////////////////////////////////////////////
 // The Option Iterators
 /////////////////////////////////////////////////////////////////////////////
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 9877a2001a0ff..fbf2035e83f46 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -909,6 +909,40 @@ impl<T: Default, E> Result<T, E> {
     }
 }
 
+impl<T: Deref, E: Deref> Result<T, E> {
+    #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+    /// Converts from `&Result<T, E>` to `Result<&T::Target, &E>`.
+    ///
+    /// Leaves the original Result in-place, creating a new one with a reference
+    /// to the original one, additionally coercing the `Ok` arm of the Result via
+    /// `Deref`.
+    pub fn deref_ok(&self) -> Result<&T::Target, &E> {
+        self.as_ref().map(|t| t.deref())
+    }
+
+    #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+    /// Converts from `&Result<T, E>` to `Result<&T, &E::Target>`.
+    ///
+    /// Leaves the original Result in-place, creating a new one with a reference
+    /// to the original one, additionally coercing the `Err` arm of the Result via
+    /// `Deref`.
+    pub fn deref_err(&self) -> Result<&T, &E::Target>
+    {
+        self.as_ref().map_err(|e| e.deref())
+    }
+
+    #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+    /// Converts from `&Result<T, E>` to `Result<&T::Target, &E::Target>`.
+    ///
+    /// Leaves the original Result in-place, creating a new one with a reference
+    /// to the original one, additionally coercing both the `Ok` and `Err` arms
+    /// of the Result via `Deref`.
+    pub fn deref(&self) -> Result<&T::Target, &E::Target>
+    {
+        self.as_ref().map(|t| t.deref()).map_err(|e| e.deref())
+    }
+}
+
 impl<T, E> Result<Option<T>, E> {
     /// Transposes a `Result` of an `Option` into an `Option` of a `Result`.
     ///
@@ -999,63 +1033,6 @@ impl<'a, T, E> IntoIterator for &'a mut Result<T, E> {
     }
 }
 
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-/// Extension trait to get a reference to a Result via the Deref trait.
-pub trait ResultDeref<T, E> {
-    /// Converts from `&Result<T, E>` to `Result<&T::Target, &E>`.
-    ///
-    /// Leaves the original Result in-place, creating a new one with a reference
-    /// to the original one, additionally coercing the `Ok` arm of the Result via
-    /// `Deref`.
-    fn deref_ok(&self) -> Result<&T::Target, &E>
-                where
-                       T: Deref;
-
-    /// Converts from `&Result<T, E>` to `Result<&T, &E::Target>`.
-    ///
-    /// Leaves the original Result in-place, creating a new one with a reference
-    /// to the original one, additionally coercing the `Err` arm of the Result via
-    /// `Deref`.
-    fn deref_err(&self) -> Result<&T, &E::Target>
-                 where
-                        E: Deref;
-
-    /// Converts from `&Result<T, E>` to `Result<&T::Target, &E::Target>`.
-    ///
-    /// Leaves the original Result in-place, creating a new one with a reference
-    /// to the original one, additionally coercing both the `Ok` and `Err` arms
-    /// of the Result via `Deref`.
-    fn deref(&self) -> Result<&T::Target, &E::Target>
-             where
-                    T: Deref,
-                    E: Deref;
-}
-
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-impl<T, E> ResultDeref<T, E> for Result<T, E> {
-    fn deref_ok(&self) -> Result<&T::Target, &E>
-                where
-                       T: Deref,
-    {
-        self.as_ref().map(|t| t.deref())
-    }
-
-    fn deref_err(&self) -> Result<&T, &E::Target>
-                 where
-                        E: Deref,
-    {
-        self.as_ref().map_err(|e| e.deref())
-    }
-
-    fn deref(&self) -> Result<&T::Target, &E::Target>
-             where
-                    T: Deref,
-                    E: Deref,
-    {
-        self.as_ref().map(|t| t.deref()).map_err(|e| e.deref())
-    }
-}
-
 /////////////////////////////////////////////////////////////////////////////
 // The Result Iterators
 /////////////////////////////////////////////////////////////////////////////

From 527e84f300a2cc36b74dcfc6a23ea9352cbf2e0b Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Thu, 26 Apr 2018 20:41:10 -0700
Subject: [PATCH 3/9] cleaned up #[unstable] attributes

---
 src/libcore/result.rs | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index fbf2035e83f46..9e302cb9f968e 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -909,8 +909,8 @@ impl<T: Default, E> Result<T, E> {
     }
 }
 
+#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
 impl<T: Deref, E: Deref> Result<T, E> {
-    #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
     /// Converts from `&Result<T, E>` to `Result<&T::Target, &E>`.
     ///
     /// Leaves the original Result in-place, creating a new one with a reference
@@ -920,7 +920,6 @@ impl<T: Deref, E: Deref> Result<T, E> {
         self.as_ref().map(|t| t.deref())
     }
 
-    #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
     /// Converts from `&Result<T, E>` to `Result<&T, &E::Target>`.
     ///
     /// Leaves the original Result in-place, creating a new one with a reference
@@ -931,7 +930,6 @@ impl<T: Deref, E: Deref> Result<T, E> {
         self.as_ref().map_err(|e| e.deref())
     }
 
-    #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
     /// Converts from `&Result<T, E>` to `Result<&T::Target, &E::Target>`.
     ///
     /// Leaves the original Result in-place, creating a new one with a reference

From b812d44a01bbc7180c11c9fdc3de3926105cbe05 Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Thu, 26 Apr 2018 20:42:44 -0700
Subject: [PATCH 4/9] added #![feature(inner_deref)] to enable
 inner_deref-related unit tests

---
 src/libcore/lib.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 0e21a3327fddf..55c5e1e7971d4 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -103,6 +103,7 @@
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(doc_alias)]
+#![feature(inner_deref)]
 
 #![cfg_attr(not(stage0), feature(mmx_target_feature))]
 #![cfg_attr(not(stage0), feature(tbm_target_feature))]

From 2bf9fbc8d61e2283cd6133b96cff2e04988bbe69 Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Fri, 27 Apr 2018 06:36:37 -0700
Subject: [PATCH 5/9] separated inner_deref Result impls

---
 src/libcore/result.rs | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index 9e302cb9f968e..c545064aadb29 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -910,7 +910,7 @@ impl<T: Default, E> Result<T, E> {
 }
 
 #[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
-impl<T: Deref, E: Deref> Result<T, E> {
+impl<T: Deref, E> Result<T, E> {
     /// Converts from `&Result<T, E>` to `Result<&T::Target, &E>`.
     ///
     /// Leaves the original Result in-place, creating a new one with a reference
@@ -919,7 +919,10 @@ impl<T: Deref, E: Deref> Result<T, E> {
     pub fn deref_ok(&self) -> Result<&T::Target, &E> {
         self.as_ref().map(|t| t.deref())
     }
+}
 
+#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+impl<T, E: Deref> Result<T, E> {
     /// Converts from `&Result<T, E>` to `Result<&T, &E::Target>`.
     ///
     /// Leaves the original Result in-place, creating a new one with a reference
@@ -929,7 +932,10 @@ impl<T: Deref, E: Deref> Result<T, E> {
     {
         self.as_ref().map_err(|e| e.deref())
     }
+}
 
+#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+impl<T: Deref, E: Deref> Result<T, E> {
     /// Converts from `&Result<T, E>` to `Result<&T::Target, &E::Target>`.
     ///
     /// Leaves the original Result in-place, creating a new one with a reference

From 8aa049e54be521c3826b0af15a87b3b4db1fb77b Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Fri, 27 Apr 2018 06:39:04 -0700
Subject: [PATCH 6/9] moved #![feature(inner_deref) to from libcore crate to
 libcore tests crate to enable related tests

---
 src/libcore/lib.rs       | 1 -
 src/libcore/tests/lib.rs | 1 +
 2 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 55c5e1e7971d4..0e21a3327fddf 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -103,7 +103,6 @@
 #![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(doc_alias)]
-#![feature(inner_deref)]
 
 #![cfg_attr(not(stage0), feature(mmx_target_feature))]
 #![cfg_attr(not(stage0), feature(tbm_target_feature))]
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index e4d277179382f..111cf58c2c69d 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -46,6 +46,7 @@
 #![feature(reverse_bits)]
 #![feature(inclusive_range_fields)]
 #![feature(iterator_find_map)]
+#![feature(inner_deref)]
 
 extern crate core;
 extern crate test;

From 17124488c7c7582fb9ab22ed87b2759ee20a4602 Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Fri, 27 Apr 2018 07:07:26 -0700
Subject: [PATCH 7/9] fixed inner_deref test case for None

---
 src/libcore/tests/option.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index 77d550c532a34..e7e48b2daa2e2 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -305,6 +305,6 @@ fn test_option_deref() {
     assert_eq!(ref_option.deref(), Some(&42));
 
     // None: &Option<T: Deref>>::None -> None
-    let ref_option = &None;
+    let ref_option: &Option<&i32> = &None;
     assert_eq!(ref_option.deref(), None);
 }

From c025fdebbada2757deccdd97219ff0313631f2ed Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Mon, 30 Apr 2018 12:51:43 -0700
Subject: [PATCH 8/9] fixed some and added more tests

---
 src/libcore/option.rs                         |   2 +-
 src/libcore/tests/option.rs                   |   8 ++
 src/libcore/tests/result.rs                   | 102 +++++++++++++++---
 .../option_deref.rs                           |  16 +++
 .../result_deref.rs                           |  16 +++
 .../result_deref_err.rs                       |  16 +++
 .../result_deref_ok.rs                        |  16 +++
 7 files changed, 158 insertions(+), 18 deletions(-)
 create mode 100644 src/test/compile-fail/issue-50264-inner-deref-trait/option_deref.rs
 create mode 100644 src/test/compile-fail/issue-50264-inner-deref-trait/result_deref.rs
 create mode 100644 src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_err.rs
 create mode 100644 src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_ok.rs

diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index 506e54ba5e4e6..deb0380171c4e 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -878,7 +878,7 @@ impl<T: Default> Option<T> {
     }
 }
 
-# [unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
 impl<T: Deref> Option<T> {
     /// Converts from `&Option<T>` to `Option<&T::Target>`.
     ///
diff --git a/src/libcore/tests/option.rs b/src/libcore/tests/option.rs
index e7e48b2daa2e2..ced7b03636a09 100644
--- a/src/libcore/tests/option.rs
+++ b/src/libcore/tests/option.rs
@@ -304,7 +304,15 @@ fn test_option_deref() {
     let ref_option = &Some(&42);
     assert_eq!(ref_option.deref(), Some(&42));
 
+    let ref_option = &Some(String::from("a result"));
+    assert_eq!(ref_option.deref(), Some("a result"));
+
+    let ref_option = &Some(vec![1, 2, 3, 4, 5]);
+    assert_eq!(ref_option.deref(), Some(&[1, 2, 3, 4, 5][..]));
+
     // None: &Option<T: Deref>>::None -> None
     let ref_option: &Option<&i32> = &None;
     assert_eq!(ref_option.deref(), None);
+
+
 }
diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index dd23467322dc9..fd0dd21401b88 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -234,21 +234,89 @@ fn test_try() {
 
 #[test]
 fn test_result_deref() {
-    // Ok(T).deref_ok() -> Result<&T, &E::Deref::Target>::Ok(&T)
-    let ref_ok: &Result<&i32, &u8> = &Ok(&42);
-    assert_eq!(ref_ok.deref_ok(), Ok(&42));
-    assert_eq!(ref_ok.deref_ok(), Ok(&42));
-    assert_eq!(ref_ok.deref(), Ok(&42));
-
-    // Err(E) -> Result<&T, &E::Deref::Target>::Err(&*E)
-    let ref_err: &Result<&i32, &u8> = &Err(&41);
-    assert_eq!(ref_err.deref_err(), Err(&41));
-    assert_eq!(ref_err.deref_err(), Err(&41));
-    assert_eq!(ref_err.deref(), Err(&41));
-
-    // &Ok(T).deref_err() -> Result<&T, &E::Deref::Target>::Ok(&T)
-    assert_eq!(ref_ok.deref_err(), Ok(&&42));
-
-    // &Err(E) -> Result<&T::Deref::Target, &E>::Err(&E)
-    assert_eq!(ref_err.deref_ok(), Err(&&41));
+    // &Result<T: Deref, E>::Ok(T).deref_ok() ->
+    //      Result<&T::Deref::Target, &E>::Ok(&*T)
+    let ref_ok = &Result::Ok::<&i32, u8>(&42);
+    let expected_result = Result::Ok::<&i32, &u8>(&42);
+    assert_eq!(ref_ok.deref_ok(), expected_result);
+
+    let ref_ok = &Result::Ok::<String, u32>(String::from("a result"));
+    let expected_result = Result::Ok::<&str, &u32>("a result");
+    assert_eq!(ref_ok.deref_ok(), expected_result);
+
+    let ref_ok = &Result::Ok::<Vec<i32>, u32>(vec![1, 2, 3, 4, 5]);
+    let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]);
+    assert_eq!(ref_ok.deref_ok(), expected_result);
+
+    // &Result<T: Deref, E: Deref>::Ok(T).deref() ->
+    //      Result<&T::Deref::Target, &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.deref(), expected_result);
+
+    let ref_ok = &Result::Ok::<String, &u32>(String::from("a result"));
+    let expected_result = Result::Ok::<&str, &u32>("a result");
+    assert_eq!(ref_ok.deref(), expected_result);
+
+    let ref_ok = &Result::Ok::<Vec<i32>, &u32>(vec![1, 2, 3, 4, 5]);
+    let expected_result = Result::Ok::<&[i32], &u32>(&[1, 2, 3, 4, 5][..]);
+    assert_eq!(ref_ok.deref(), expected_result);
+
+    // &Result<T, E: Deref>::Err(T).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.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.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][..]);
+    assert_eq!(ref_err.deref_err(), expected_result);
+
+    // &Result<T: Deref, E: Deref>::Err(T).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.deref(), 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.deref(), 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][..]);
+    assert_eq!(ref_err.deref(), expected_result);
+
+    // *Odd corner cases (tested for completeness)*
+
+    // &Result<T, E: Deref>::Ok(T).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.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.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.deref_err(), expected_result);
+
+    // &Result<T: Deref, E>::Err(E).deref_ok() ->
+    //      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.deref_ok(), expected_result);
+
+    let ref_err = &Result::Err::<&u32, &str>("an error");
+    let expected_result = Result::Err::<&u32, &&str>(&"an error");
+    assert_eq!(ref_err.deref_ok(), 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.deref_ok(), expected_result);
 }
diff --git a/src/test/compile-fail/issue-50264-inner-deref-trait/option_deref.rs b/src/test/compile-fail/issue-50264-inner-deref-trait/option_deref.rs
new file mode 100644
index 0000000000000..4c67fb3bef103
--- /dev/null
+++ b/src/test/compile-fail/issue-50264-inner-deref-trait/option_deref.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+#![feature(inner_deref)]
+
+fn main() {
+    let _result = &Some(42).deref();
+//~^ ERROR no method named `deref` found for type `std::option::Option<{integer}>`
+}
diff --git a/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref.rs b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref.rs
new file mode 100644
index 0000000000000..73bdf0b920907
--- /dev/null
+++ b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+#![feature(inner_deref)]
+
+fn main() {
+    let _result = &Ok(42).deref();
+//~^ ERROR no method named `deref` found
+}
diff --git a/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_err.rs b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_err.rs
new file mode 100644
index 0000000000000..5d1e7472d8f18
--- /dev/null
+++ b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_err.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+#![feature(inner_deref)]
+
+fn main() {
+    let _result = &Err(41).deref_err();
+//~^ ERROR no method named `deref_err` found
+}
diff --git a/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_ok.rs b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_ok.rs
new file mode 100644
index 0000000000000..bee8e0c062bae
--- /dev/null
+++ b/src/test/compile-fail/issue-50264-inner-deref-trait/result_deref_ok.rs
@@ -0,0 +1,16 @@
+// Copyright 2018 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.
+
+#![feature(inner_deref)]
+
+fn main() {
+    let _result = &Ok(42).deref_ok();
+//~^ ERROR no method named `deref_ok` found
+}

From e1d5509bf381d978a1894b6ba869c3b56dd3eeca Mon Sep 17 00:00:00 2001
From: Brad Gibson <b2b@humanenginuity.com>
Date: Wed, 2 May 2018 19:16:29 -0700
Subject: [PATCH 9/9] Added comments providing justification for support of
 calling deref_* with wrong variant

---
 src/libcore/tests/result.rs | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/libcore/tests/result.rs b/src/libcore/tests/result.rs
index fd0dd21401b88..f8b5ea5e16e48 100644
--- a/src/libcore/tests/result.rs
+++ b/src/libcore/tests/result.rs
@@ -290,7 +290,11 @@ fn test_result_deref() {
     let expected_result = Result::Err::<&u32, &[i32]>(&[5, 4, 3, 2, 1][..]);
     assert_eq!(ref_err.deref(), expected_result);
 
-    // *Odd corner cases (tested for completeness)*
+    // The following cases test calling deref_* with the wrong variant (i.e.
+    // `deref_ok()` with a `Result::Err()`, or `deref_err()` with a `Result::Ok()`.
+    // While unusual, these cases are supported to ensure that an `inner_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).deref_err() ->
     //      Result<&T, &E::Deref::Target>::Ok(&T)