diff options
| author | Yuki Okushi <huyuumi.dev@gmail.com> | 2021-01-27 04:43:14 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-01-27 04:43:14 +0900 |
| commit | fe6b3a97921eb59502dfca13505e3ef68f5289bb (patch) | |
| tree | 00c9f09282ed445cd97b73d099bec67b846126b8 | |
| parent | f85fd8196827c191dfe9fa46ad7e3a8f38a7a894 (diff) | |
| parent | 01250fcec6c77552b0f7aac11ed833412294ccba (diff) | |
| download | rust-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.rs | 34 | ||||
| -rw-r--r-- | library/core/src/result.rs | 70 | ||||
| -rw-r--r-- | library/core/tests/lib.rs | 1 | ||||
| -rw-r--r-- | library/core/tests/option.rs | 7 | ||||
| -rw-r--r-- | library/core/tests/result.rs | 12 |
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); |
