about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <huyuumi.dev@gmail.com>2021-01-27 04:43:14 +0900
committerGitHub <noreply@github.com>2021-01-27 04:43:14 +0900
commitfe6b3a97921eb59502dfca13505e3ef68f5289bb (patch)
tree00c9f09282ed445cd97b73d099bec67b846126b8
parentf85fd8196827c191dfe9fa46ad7e3a8f38a7a894 (diff)
parent01250fcec6c77552b0f7aac11ed833412294ccba (diff)
downloadrust-fe6b3a97921eb59502dfca13505e3ef68f5289bb.tar.gz
rust-fe6b3a97921eb59502dfca13505e3ef68f5289bb.zip
Rollup merge of #80876 - ojeda:option-result-unwrap_unchecked, r=m-ou-se
Add `unwrap_unchecked()` methods for `Option` and `Result`

In particular:
  - `unwrap_unchecked()` for `Option`.
  - `unwrap_unchecked()` and `unwrap_err_unchecked()` for `Result`.

These complement other `*_unchecked()` methods in `core` etc.

Currently there are a couple of places it may be used inside rustc (`LinkedList`, `BTree`). It is also easy to find other repositories with similar functionality.

Fixes #48278.
-rw-r--r--library/core/src/option.rs34
-rw-r--r--library/core/src/result.rs70
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/option.rs7
-rw-r--r--library/core/tests/result.rs12
5 files changed, 123 insertions, 1 deletions
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 0051c9eede0..14e4e4da3b9 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -428,6 +428,40 @@ impl<T> Option<T> {
         }
     }
 
+    /// Returns the contained [`Some`] value, consuming the `self` value,
+    /// without checking that the value is not [`None`].
+    ///
+    /// # Safety
+    ///
+    /// Calling this method on [`None`] is *[undefined behavior]*.
+    ///
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_result_unwrap_unchecked)]
+    /// let x = Some("air");
+    /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
+    /// ```
+    ///
+    /// ```no_run
+    /// #![feature(option_result_unwrap_unchecked)]
+    /// let x: Option<&str> = None;
+    /// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); // Undefined behavior!
+    /// ```
+    #[inline]
+    #[track_caller]
+    #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
+    pub unsafe fn unwrap_unchecked(self) -> T {
+        debug_assert!(self.is_some());
+        match self {
+            Some(val) => val,
+            // SAFETY: the safety contract must be upheld by the caller.
+            None => unsafe { hint::unreachable_unchecked() },
+        }
+    }
+
     /////////////////////////////////////////////////////////////////////////
     // Transforming contained values
     /////////////////////////////////////////////////////////////////////////
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index d6d17625729..a43ba5882ed 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -229,7 +229,7 @@
 
 use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
 use crate::ops::{self, Deref, DerefMut};
-use crate::{convert, fmt};
+use crate::{convert, fmt, hint};
 
 /// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
 ///
@@ -821,6 +821,74 @@ impl<T, E> Result<T, E> {
             Err(e) => op(e),
         }
     }
+
+    /// Returns the contained [`Ok`] value, consuming the `self` value,
+    /// without checking that the value is not an [`Err`].
+    ///
+    /// # Safety
+    ///
+    /// Calling this method on an [`Err`] is *[undefined behavior]*.
+    ///
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_result_unwrap_unchecked)]
+    /// let x: Result<u32, &str> = Ok(2);
+    /// assert_eq!(unsafe { x.unwrap_unchecked() }, 2);
+    /// ```
+    ///
+    /// ```no_run
+    /// #![feature(option_result_unwrap_unchecked)]
+    /// let x: Result<u32, &str> = Err("emergency failure");
+    /// unsafe { x.unwrap_unchecked(); } // Undefined behavior!
+    /// ```
+    #[inline]
+    #[track_caller]
+    #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
+    pub unsafe fn unwrap_unchecked(self) -> T {
+        debug_assert!(self.is_ok());
+        match self {
+            Ok(t) => t,
+            // SAFETY: the safety contract must be upheld by the caller.
+            Err(_) => unsafe { hint::unreachable_unchecked() },
+        }
+    }
+
+    /// Returns the contained [`Err`] value, consuming the `self` value,
+    /// without checking that the value is not an [`Ok`].
+    ///
+    /// # Safety
+    ///
+    /// Calling this method on an [`Ok`] is *[undefined behavior]*.
+    ///
+    /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(option_result_unwrap_unchecked)]
+    /// let x: Result<u32, &str> = Ok(2);
+    /// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior!
+    /// ```
+    ///
+    /// ```
+    /// #![feature(option_result_unwrap_unchecked)]
+    /// let x: Result<u32, &str> = Err("emergency failure");
+    /// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure");
+    /// ```
+    #[inline]
+    #[track_caller]
+    #[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
+    pub unsafe fn unwrap_err_unchecked(self) -> E {
+        debug_assert!(self.is_err());
+        match self {
+            // SAFETY: the safety contract must be upheld by the caller.
+            Ok(_) => unsafe { hint::unreachable_unchecked() },
+            Err(e) => e,
+        }
+    }
 }
 
 impl<T: Copy, E> Result<&T, E> {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 98f5982fbb2..b7a406c30e9 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -64,6 +64,7 @@
 #![feature(const_raw_ptr_deref)]
 #![feature(never_type)]
 #![feature(unwrap_infallible)]
+#![feature(option_result_unwrap_unchecked)]
 #![feature(option_unwrap_none)]
 #![feature(peekable_next_if)]
 #![feature(peekable_peek_mut)]
diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs
index 5388b475624..9470451278c 100644
--- a/library/core/tests/option.rs
+++ b/library/core/tests/option.rs
@@ -161,6 +161,13 @@ fn test_unwrap_or_else() {
 }
 
 #[test]
+fn test_unwrap_unchecked() {
+    assert_eq!(unsafe { Some(1).unwrap_unchecked() }, 1);
+    let s = unsafe { Some("hello".to_string()).unwrap_unchecked() };
+    assert_eq!(s, "hello");
+}
+
+#[test]
 fn test_iter() {
     let val = 5;
 
diff --git a/library/core/tests/result.rs b/library/core/tests/result.rs
index 81660870e95..7aa44c6e593 100644
--- a/library/core/tests/result.rs
+++ b/library/core/tests/result.rs
@@ -120,6 +120,18 @@ pub fn test_unwrap_or_else_panic() {
 }
 
 #[test]
+fn test_unwrap_unchecked() {
+    let ok: Result<isize, &'static str> = Ok(100);
+    assert_eq!(unsafe { ok.unwrap_unchecked() }, 100);
+}
+
+#[test]
+fn test_unwrap_err_unchecked() {
+    let ok_err: Result<isize, &'static str> = Err("Err");
+    assert_eq!(unsafe { ok_err.unwrap_err_unchecked() }, "Err");
+}
+
+#[test]
 pub fn test_expect_ok() {
     let ok: Result<isize, &'static str> = Ok(100);
     assert_eq!(ok.expect("Unexpected error"), 100);