Skip to content
4 changes: 4 additions & 0 deletions compiler/rustc_feature/src/active.rs
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,10 @@ declare_features! (
(active, object_safe_for_dispatch, "1.40.0", Some(43561), None),
/// Allows using `#[optimize(X)]`.
(active, optimize_attribute, "1.34.0", Some(54882), None),
/// Allows using `Option<&Option<T>>::flatten_ref()`,
/// Option<&mut Option<T>>::flatten_ref()` and
/// Option<&mut Option<T>>::flatten_mut()`
(active, option_reference_flattening, "CURRENT_RUSTC_VERSION", None, None),
/// Allows `extern "platform-intrinsic" { ... }`.
(active, platform_intrinsics, "1.4.0", Some(27731), None),
/// Allows using `#![plugin(myplugin)]`.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,7 @@ symbols! {
optin_builtin_traits,
option,
option_env,
option_reference_flattening,
options,
or,
or_patterns,
Expand Down
89 changes: 89 additions & 0 deletions library/core/src/option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2606,3 +2606,92 @@ impl<T> Option<Option<T>> {
}
}
}

impl<'a, T> Option<&'a Option<T>> {
/// Converts from `Option<&Option<T>>` to `Option<&T>`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(option_reference_flattening)]
///
/// let x: Option<&Option<u32>> = Some(&Some(6));
/// assert_eq!(&Some(6), x.flatten_ref());
///
/// let x: Option<&Option<u32>> = Some(&None);
/// assert_eq!(&None, x.flatten_ref());
///
/// let x: Option<&Option<u32>> = None;
/// assert_eq!(&None, x.flatten_ref());
/// ```
#[inline]
#[unstable(feature = "option_reference_flattening", issue = "none")]
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn flatten_ref(self) -> &'a Option<T> {
match self {
Some(inner) => inner,
None => const { &None },
}
}
}

impl<'a, T> Option<&'a mut Option<T>> {
/// Converts from `Option<&mut Option<T>>` to `Option<&T>`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(option_reference_flattening)]
///
/// let x: Option<&mut Option<u32>> = Some(&mut Some(6));
/// assert_eq!(&Some(6), x.flatten_ref());
///
/// let x: Option<&mut Option<u32>> = Some(&mut None);
/// assert_eq!(&None, x.flatten_ref());
///
/// let x: Option<&mut Option<u32>> = None;
/// assert_eq!(&None, x.flatten_ref());
/// ```
#[unstable(feature = "option_reference_flattening", issue = "none")]
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn flatten_ref(self) -> &'a Option<T> {
match self {
Some(inner) => inner,
None => const { &None },
}
}

/// Converts from `Option<&mut Option<T>>` to `Option<&mut T>`.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// #![feature(option_reference_flattening)]
///
/// let y: &mut Option<u32> = &mut Some(6);
/// let x: Option<&mut Option<u32>> = Some(y);
/// assert_eq!(Some(&mut 6), x.flatten_mut());
///
/// let y: &mut Option<u32> = &mut None;
/// let x: Option<&mut Option<u32>> = Some(y);
/// assert_eq!(None, x.flatten_mut());
///
/// let x: Option<&mut Option<u32>> = None;
/// assert_eq!(None, x.flatten_mut());
/// ```
#[inline]
#[unstable(feature = "option_reference_flattening", issue = "none")]
#[rustc_const_unstable(feature = "const_option", issue = "67441")]
pub const fn flatten_mut(self) -> Option<&'a mut T> {
match self {
Some(inner) => inner.as_mut(),
None => None,
}
}
}