Skip to content

Commit

Permalink
Rollup merge of rust-lang#86828 - lambinoo:67441-const-fn-copied-take…
Browse files Browse the repository at this point in the history
…-replace, r=joshtriplett

const fn for option copied, take & replace

Tracking issue: [rust-lang#67441](rust-lang#67441)

Adding const fn for the copied, take and replace method of Option. Also adding necessary unit test.

It's my first contribution so I am pretty sure I don't know what I'm doing but there's a first for everything!
  • Loading branch information
Manishearth committed Oct 4, 2021
2 parents 22714ed + 10ddabc commit 287af04
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 7 deletions.
1 change: 1 addition & 0 deletions library/core/src/lib.rs
Expand Up @@ -91,6 +91,7 @@
#![feature(const_maybe_uninit_assume_init)]
#![feature(const_option)]
#![feature(const_pin)]
#![feature(const_replace)]
#![feature(const_ptr_offset)]
#![feature(const_ptr_offset_from)]
#![feature(const_ptr_read)]
Expand Down
23 changes: 16 additions & 7 deletions library/core/src/option.rs
Expand Up @@ -544,8 +544,8 @@ impl<T> Option<T> {
/// ```
#[must_use = "if you intended to assert that this has a value, consider `.unwrap()` instead"]
#[inline]
#[rustc_const_stable(feature = "const_option", since = "1.48.0")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_option", since = "1.48.0")]
pub const fn is_some(&self) -> bool {
matches!(*self, Some(_))
}
Expand All @@ -564,8 +564,8 @@ impl<T> Option<T> {
#[must_use = "if you intended to assert that this doesn't have a value, consider \
`.and_then(|_| panic!(\"`Option` had a value when expected `None`\"))` instead"]
#[inline]
#[rustc_const_stable(feature = "const_option", since = "1.48.0")]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_option", since = "1.48.0")]
pub const fn is_none(&self) -> bool {
!self.is_some()
}
Expand Down Expand Up @@ -1318,8 +1318,10 @@ impl<T> Option<T> {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn take(&mut self) -> Option<T> {
mem::take(self)
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn take(&mut self) -> Option<T> {
// FIXME replace `mem::replace` by `mem::take` when the latter is const ready
mem::replace(self, None)
}

/// Replaces the actual value in the option by the value given in parameter,
Expand All @@ -1340,8 +1342,9 @@ impl<T> Option<T> {
/// assert_eq!(old, None);
/// ```
#[inline]
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
#[stable(feature = "option_replace", since = "1.31.0")]
pub fn replace(&mut self, value: T) -> Option<T> {
pub const fn replace(&mut self, value: T) -> Option<T> {
mem::replace(self, Some(value))
}

Expand Down Expand Up @@ -1446,8 +1449,14 @@ impl<T: Copy> Option<&T> {
/// assert_eq!(copied, Some(12));
/// ```
#[stable(feature = "copied", since = "1.35.0")]
pub fn copied(self) -> Option<T> {
self.map(|&t| t)
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn copied(self) -> Option<T> {
// FIXME: this implementation, which sidesteps using `Option::map` since it's not const
// ready yet, should be reverted when possible to avoid code repetition
match self {
Some(&v) => Some(v),
None => None,
}
}
}

Expand Down
13 changes: 13 additions & 0 deletions library/core/tests/option.rs
Expand Up @@ -367,6 +367,19 @@ fn option_const() {

const IS_NONE: bool = OPTION.is_none();
assert!(!IS_NONE);

const COPIED: Option<usize> = OPTION.as_ref().copied();
assert_eq!(COPIED, OPTION);
}

#[test]
const fn option_const_mut() {
// test that the methods of `Option` that take mutable references are usable in a const context

let mut option: Option<usize> = Some(32);

let _take = option.take();
let _replace = option.replace(42);
}

#[test]
Expand Down

0 comments on commit 287af04

Please sign in to comment.