Skip to content

Commit fe6b3a9

Browse files
authored
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.
2 parents f85fd81 + 01250fc commit fe6b3a9

File tree

5 files changed

+123
-1
lines changed

5 files changed

+123
-1
lines changed

library/core/src/option.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,40 @@ impl<T> Option<T> {
428428
}
429429
}
430430

431+
/// Returns the contained [`Some`] value, consuming the `self` value,
432+
/// without checking that the value is not [`None`].
433+
///
434+
/// # Safety
435+
///
436+
/// Calling this method on [`None`] is *[undefined behavior]*.
437+
///
438+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
439+
///
440+
/// # Examples
441+
///
442+
/// ```
443+
/// #![feature(option_result_unwrap_unchecked)]
444+
/// let x = Some("air");
445+
/// assert_eq!(unsafe { x.unwrap_unchecked() }, "air");
446+
/// ```
447+
///
448+
/// ```no_run
449+
/// #![feature(option_result_unwrap_unchecked)]
450+
/// let x: Option<&str> = None;
451+
/// assert_eq!(unsafe { x.unwrap_unchecked() }, "air"); // Undefined behavior!
452+
/// ```
453+
#[inline]
454+
#[track_caller]
455+
#[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
456+
pub unsafe fn unwrap_unchecked(self) -> T {
457+
debug_assert!(self.is_some());
458+
match self {
459+
Some(val) => val,
460+
// SAFETY: the safety contract must be upheld by the caller.
461+
None => unsafe { hint::unreachable_unchecked() },
462+
}
463+
}
464+
431465
/////////////////////////////////////////////////////////////////////////
432466
// Transforming contained values
433467
/////////////////////////////////////////////////////////////////////////

library/core/src/result.rs

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@
229229

230230
use crate::iter::{self, FromIterator, FusedIterator, TrustedLen};
231231
use crate::ops::{self, Deref, DerefMut};
232-
use crate::{convert, fmt};
232+
use crate::{convert, fmt, hint};
233233

234234
/// `Result` is a type that represents either success ([`Ok`]) or failure ([`Err`]).
235235
///
@@ -821,6 +821,74 @@ impl<T, E> Result<T, E> {
821821
Err(e) => op(e),
822822
}
823823
}
824+
825+
/// Returns the contained [`Ok`] value, consuming the `self` value,
826+
/// without checking that the value is not an [`Err`].
827+
///
828+
/// # Safety
829+
///
830+
/// Calling this method on an [`Err`] is *[undefined behavior]*.
831+
///
832+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
833+
///
834+
/// # Examples
835+
///
836+
/// ```
837+
/// #![feature(option_result_unwrap_unchecked)]
838+
/// let x: Result<u32, &str> = Ok(2);
839+
/// assert_eq!(unsafe { x.unwrap_unchecked() }, 2);
840+
/// ```
841+
///
842+
/// ```no_run
843+
/// #![feature(option_result_unwrap_unchecked)]
844+
/// let x: Result<u32, &str> = Err("emergency failure");
845+
/// unsafe { x.unwrap_unchecked(); } // Undefined behavior!
846+
/// ```
847+
#[inline]
848+
#[track_caller]
849+
#[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
850+
pub unsafe fn unwrap_unchecked(self) -> T {
851+
debug_assert!(self.is_ok());
852+
match self {
853+
Ok(t) => t,
854+
// SAFETY: the safety contract must be upheld by the caller.
855+
Err(_) => unsafe { hint::unreachable_unchecked() },
856+
}
857+
}
858+
859+
/// Returns the contained [`Err`] value, consuming the `self` value,
860+
/// without checking that the value is not an [`Ok`].
861+
///
862+
/// # Safety
863+
///
864+
/// Calling this method on an [`Ok`] is *[undefined behavior]*.
865+
///
866+
/// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
867+
///
868+
/// # Examples
869+
///
870+
/// ```no_run
871+
/// #![feature(option_result_unwrap_unchecked)]
872+
/// let x: Result<u32, &str> = Ok(2);
873+
/// unsafe { x.unwrap_err_unchecked() }; // Undefined behavior!
874+
/// ```
875+
///
876+
/// ```
877+
/// #![feature(option_result_unwrap_unchecked)]
878+
/// let x: Result<u32, &str> = Err("emergency failure");
879+
/// assert_eq!(unsafe { x.unwrap_err_unchecked() }, "emergency failure");
880+
/// ```
881+
#[inline]
882+
#[track_caller]
883+
#[unstable(feature = "option_result_unwrap_unchecked", reason = "newly added", issue = "81383")]
884+
pub unsafe fn unwrap_err_unchecked(self) -> E {
885+
debug_assert!(self.is_err());
886+
match self {
887+
// SAFETY: the safety contract must be upheld by the caller.
888+
Ok(_) => unsafe { hint::unreachable_unchecked() },
889+
Err(e) => e,
890+
}
891+
}
824892
}
825893

826894
impl<T: Copy, E> Result<&T, E> {

library/core/tests/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#![feature(const_raw_ptr_deref)]
6565
#![feature(never_type)]
6666
#![feature(unwrap_infallible)]
67+
#![feature(option_result_unwrap_unchecked)]
6768
#![feature(option_unwrap_none)]
6869
#![feature(peekable_next_if)]
6970
#![feature(peekable_peek_mut)]

library/core/tests/option.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@ fn test_unwrap_or_else() {
160160
assert_eq!(x.unwrap_or_else(|| 2), 2);
161161
}
162162

163+
#[test]
164+
fn test_unwrap_unchecked() {
165+
assert_eq!(unsafe { Some(1).unwrap_unchecked() }, 1);
166+
let s = unsafe { Some("hello".to_string()).unwrap_unchecked() };
167+
assert_eq!(s, "hello");
168+
}
169+
163170
#[test]
164171
fn test_iter() {
165172
let val = 5;

library/core/tests/result.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,18 @@ pub fn test_unwrap_or_else_panic() {
119119
let _: isize = bad_err.unwrap_or_else(handler);
120120
}
121121

122+
#[test]
123+
fn test_unwrap_unchecked() {
124+
let ok: Result<isize, &'static str> = Ok(100);
125+
assert_eq!(unsafe { ok.unwrap_unchecked() }, 100);
126+
}
127+
128+
#[test]
129+
fn test_unwrap_err_unchecked() {
130+
let ok_err: Result<isize, &'static str> = Err("Err");
131+
assert_eq!(unsafe { ok_err.unwrap_err_unchecked() }, "Err");
132+
}
133+
122134
#[test]
123135
pub fn test_expect_ok() {
124136
let ok: Result<isize, &'static str> = Ok(100);

0 commit comments

Comments
 (0)