Rollup merge of #130518 - scottmcm:stabilize-controlflow-extra, r=dtolnay

Stabilize the `map`/`value` methods on `ControlFlow`

And fix the stability attribute on the `pub use` in `core::ops`.

libs-api in https://github.com/rust-lang/rust/issues/75744#issuecomment-2231214910 seemed reasonably happy with naming for these, so let's try for an FCP.

Summary:
```rust
impl<B, C> ControlFlow<B, C> {
    pub fn break_value(self) -> Option<B>;
    pub fn map_break<T>(self, f: impl FnOnce(B) -> T) -> ControlFlow<T, C>;
    pub fn continue_value(self) -> Option<C>;
    pub fn map_continue<T>(self, f: impl FnOnce(C) -> T) -> ControlFlow<B, T>;
}
```

Resolves #75744

``@rustbot`` label +needs-fcp +t-libs-api -t-libs

---

Aside, in case it keeps someone else from going down the same dead end: I looked at the `{break,continue}_value` methods and tried to make them `const` as part of this, but that's disallowed because of not having `const Drop`, so put it back to not even unstably-const.
This commit is contained in:
Jubilee 2024-10-04 14:11:34 -07:00 committed by GitHub
commit 5a8fcab713
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
32 changed files with 15 additions and 53 deletions

View File

@ -5,7 +5,6 @@
#![doc(rust_logo)] #![doc(rust_logo)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(file_buffered)] #![feature(file_buffered)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(never_type)] #![feature(never_type)]

View File

@ -62,7 +62,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)] #![doc(rust_logo)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]
#![feature(let_chains)] #![feature(let_chains)]

View File

@ -3,7 +3,6 @@
#![allow(rustc::untranslatable_diagnostic)] #![allow(rustc::untranslatable_diagnostic)]
#![feature(array_windows)] #![feature(array_windows)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(never_type)] #![feature(never_type)]

View File

@ -20,7 +20,6 @@
#![doc(rust_logo)] #![doc(rust_logo)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(extend_one)] #![feature(extend_one)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]

View File

@ -32,7 +32,6 @@
#![feature(array_windows)] #![feature(array_windows)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(extract_if)] #![feature(extract_if)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_order_by)] #![feature(iter_order_by)]

View File

@ -2,7 +2,6 @@
#![allow(internal_features)] #![allow(internal_features)]
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![doc(rust_logo)] #![doc(rust_logo)]
#![feature(control_flow_enum)]
#![feature(coroutines)] #![feature(coroutines)]
#![feature(decl_macro)] #![feature(decl_macro)]
#![feature(error_iter)] #![feature(error_iter)]

View File

@ -20,7 +20,6 @@
#![feature(associated_type_defaults)] #![feature(associated_type_defaults)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(cfg_version)] #![feature(cfg_version)]
#![feature(control_flow_enum)]
#![feature(extract_if)] #![feature(extract_if)]
#![feature(if_let_guard)] #![feature(if_let_guard)]
#![feature(iter_intersperse)] #![feature(iter_intersperse)]

View File

@ -171,14 +171,13 @@ pub fn is_continue(&self) -> bool {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(control_flow_enum)]
/// use std::ops::ControlFlow; /// use std::ops::ControlFlow;
/// ///
/// assert_eq!(ControlFlow::<i32, String>::Break(3).break_value(), Some(3)); /// assert_eq!(ControlFlow::<i32, String>::Break(3).break_value(), Some(3));
/// assert_eq!(ControlFlow::<String, i32>::Continue(3).break_value(), None); /// assert_eq!(ControlFlow::<String, i32>::Continue(3).break_value(), None);
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")]
pub fn break_value(self) -> Option<B> { pub fn break_value(self) -> Option<B> {
match self { match self {
ControlFlow::Continue(..) => None, ControlFlow::Continue(..) => None,
@ -189,11 +188,8 @@ pub fn break_value(self) -> Option<B> {
/// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` by applying a function /// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` by applying a function
/// to the break value in case it exists. /// to the break value in case it exists.
#[inline] #[inline]
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")]
pub fn map_break<T, F>(self, f: F) -> ControlFlow<T, C> pub fn map_break<T>(self, f: impl FnOnce(B) -> T) -> ControlFlow<T, C> {
where
F: FnOnce(B) -> T,
{
match self { match self {
ControlFlow::Continue(x) => ControlFlow::Continue(x), ControlFlow::Continue(x) => ControlFlow::Continue(x),
ControlFlow::Break(x) => ControlFlow::Break(f(x)), ControlFlow::Break(x) => ControlFlow::Break(f(x)),
@ -206,14 +202,13 @@ pub fn map_break<T, F>(self, f: F) -> ControlFlow<T, C>
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// #![feature(control_flow_enum)]
/// use std::ops::ControlFlow; /// use std::ops::ControlFlow;
/// ///
/// assert_eq!(ControlFlow::<i32, String>::Break(3).continue_value(), None); /// assert_eq!(ControlFlow::<i32, String>::Break(3).continue_value(), None);
/// assert_eq!(ControlFlow::<String, i32>::Continue(3).continue_value(), Some(3)); /// assert_eq!(ControlFlow::<String, i32>::Continue(3).continue_value(), Some(3));
/// ``` /// ```
#[inline] #[inline]
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")]
pub fn continue_value(self) -> Option<C> { pub fn continue_value(self) -> Option<C> {
match self { match self {
ControlFlow::Continue(x) => Some(x), ControlFlow::Continue(x) => Some(x),
@ -224,11 +219,8 @@ pub fn continue_value(self) -> Option<C> {
/// Maps `ControlFlow<B, C>` to `ControlFlow<B, T>` by applying a function /// Maps `ControlFlow<B, C>` to `ControlFlow<B, T>` by applying a function
/// to the continue value in case it exists. /// to the continue value in case it exists.
#[inline] #[inline]
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[stable(feature = "control_flow_enum", since = "CURRENT_RUSTC_VERSION")]
pub fn map_continue<T, F>(self, f: F) -> ControlFlow<B, T> pub fn map_continue<T>(self, f: impl FnOnce(C) -> T) -> ControlFlow<B, T> {
where
F: FnOnce(C) -> T,
{
match self { match self {
ControlFlow::Continue(x) => ControlFlow::Continue(f(x)), ControlFlow::Continue(x) => ControlFlow::Continue(f(x)),
ControlFlow::Break(x) => ControlFlow::Break(x), ControlFlow::Break(x) => ControlFlow::Break(x),

View File

@ -162,7 +162,7 @@
pub use self::bit::{BitAnd, BitOr, BitXor, Not, Shl, Shr}; pub use self::bit::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
#[stable(feature = "op_assign_traits", since = "1.8.0")] #[stable(feature = "op_assign_traits", since = "1.8.0")]
pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign}; pub use self::bit::{BitAndAssign, BitOrAssign, BitXorAssign, ShlAssign, ShrAssign};
#[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")] #[stable(feature = "control_flow_enum_type", since = "1.55.0")]
pub use self::control_flow::ControlFlow; pub use self::control_flow::ControlFlow;
#[unstable(feature = "coroutine_trait", issue = "43122")] #[unstable(feature = "coroutine_trait", issue = "43122")]
pub use self::coroutine::{Coroutine, CoroutineState}; pub use self::coroutine::{Coroutine, CoroutineState};

View File

@ -1,7 +1,6 @@
#![feature(array_windows)] #![feature(array_windows)]
#![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_into_iter_sorted)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(f128)] #![feature(f128)]
#![feature(f16)] #![feature(f16)]
#![feature(if_let_guard)] #![feature(if_let_guard)]

View File

@ -1,6 +1,5 @@
#![feature(array_chunks)] #![feature(array_chunks)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(control_flow_enum)]
#![feature(f128)] #![feature(f128)]
#![feature(f16)] #![feature(f16)]
#![feature(if_let_guard)] #![feature(if_let_guard)]

View File

@ -2,7 +2,6 @@
//@ compile-flags: -Zmir-enable-passes=+Inline //@ compile-flags: -Zmir-enable-passes=+Inline
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
#![feature(control_flow_enum)]
#![feature(try_trait_v2)] #![feature(try_trait_v2)]
#![feature(custom_mir, core_intrinsics, rustc_attrs)] #![feature(custom_mir, core_intrinsics, rustc_attrs)]

View File

@ -1,5 +1,4 @@
// skip-filecheck // skip-filecheck
#![feature(control_flow_enum)]
#![feature(try_trait_v2)] #![feature(try_trait_v2)]
//@ compile-flags: -Zunsound-mir-opts //@ compile-flags: -Zunsound-mir-opts

View File

@ -8,7 +8,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#![feature(ascii_char, ascii_char_variants)] #![feature(ascii_char, ascii_char_variants)]
extern crate rustc_hir; extern crate rustc_hir;

View File

@ -10,7 +10,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#![feature(ascii_char, ascii_char_variants)] #![feature(ascii_char, ascii_char_variants)]
extern crate rustc_hir; extern crate rustc_hir;

View File

@ -7,7 +7,6 @@
//@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837 //@ ignore-windows-gnu mingw has troubles with linking https://github.com/rust-lang/rust/pull/116837
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(control_flow_enum)]
extern crate rustc_hir; extern crate rustc_hir;
#[macro_use] #[macro_use]

View File

@ -10,7 +10,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
extern crate rustc_middle; extern crate rustc_middle;
#[macro_use] #[macro_use]

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -8,7 +8,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#![feature(ascii_char, ascii_char_variants)] #![feature(ascii_char, ascii_char_variants)]
extern crate rustc_hir; extern crate rustc_hir;

View File

@ -10,7 +10,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
extern crate rustc_hir; extern crate rustc_hir;
#[macro_use] #[macro_use]

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
extern crate rustc_hir; extern crate rustc_hir;
#[macro_use] #[macro_use]

View File

@ -10,7 +10,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -9,7 +9,6 @@
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(control_flow_enum)]
#[macro_use] #[macro_use]
extern crate rustc_smir; extern crate rustc_smir;

View File

@ -1,5 +1,3 @@
#![feature(control_flow_enum)]
use std::ops::ControlFlow; use std::ops::ControlFlow;
fn result_to_result() -> Result<u64, u8> { fn result_to_result() -> Result<u64, u8> {

View File

@ -1,5 +1,5 @@
error[E0277]: `?` couldn't convert the error to `u8` error[E0277]: `?` couldn't convert the error to `u8`
--> $DIR/bad-interconversion.rs:6:20 --> $DIR/bad-interconversion.rs:4:20
| |
LL | fn result_to_result() -> Result<u64, u8> { LL | fn result_to_result() -> Result<u64, u8> {
| --------------- expected `u8` because of this | --------------- expected `u8` because of this
@ -15,7 +15,7 @@ LL | Ok(Err(123_i32)?)
= note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>` = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result` error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
--> $DIR/bad-interconversion.rs:11:12 --> $DIR/bad-interconversion.rs:9:12
| |
LL | fn option_to_result() -> Result<u64, String> { LL | fn option_to_result() -> Result<u64, String> {
| -------------------------------------------- this function returns a `Result` | -------------------------------------------- this function returns a `Result`
@ -26,7 +26,7 @@ LL | Some(3)?;
= help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>` = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result` error[E0277]: the `?` operator can only be used on `Result`s in a function that returns `Result`
--> $DIR/bad-interconversion.rs:17:31 --> $DIR/bad-interconversion.rs:15:31
| |
LL | fn control_flow_to_result() -> Result<u64, String> { LL | fn control_flow_to_result() -> Result<u64, String> {
| -------------------------------------------------- this function returns a `Result` | -------------------------------------------------- this function returns a `Result`
@ -37,7 +37,7 @@ LL | Ok(ControlFlow::Break(123)?)
= help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>` = help: the trait `FromResidual<Result<Infallible, E>>` is implemented for `Result<T, F>`
error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option` error[E0277]: the `?` operator can only be used on `Option`s, not `Result`s, in a function that returns `Option`
--> $DIR/bad-interconversion.rs:22:22 --> $DIR/bad-interconversion.rs:20:22
| |
LL | fn result_to_option() -> Option<u16> { LL | fn result_to_option() -> Option<u16> {
| ------------------------------------ this function returns an `Option` | ------------------------------------ this function returns an `Option`
@ -48,7 +48,7 @@ LL | Some(Err("hello")?)
= help: the trait `FromResidual<Option<Infallible>>` is implemented for `Option<T>` = help: the trait `FromResidual<Option<Infallible>>` is implemented for `Option<T>`
error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option` error[E0277]: the `?` operator can only be used on `Option`s in a function that returns `Option`
--> $DIR/bad-interconversion.rs:27:33 --> $DIR/bad-interconversion.rs:25:33
| |
LL | fn control_flow_to_option() -> Option<u64> { LL | fn control_flow_to_option() -> Option<u64> {
| ------------------------------------------ this function returns an `Option` | ------------------------------------------ this function returns an `Option`
@ -59,7 +59,7 @@ LL | Some(ControlFlow::Break(123)?)
= help: the trait `FromResidual<Option<Infallible>>` is implemented for `Option<T>` = help: the trait `FromResidual<Option<Infallible>>` is implemented for `Option<T>`
error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
--> $DIR/bad-interconversion.rs:32:39 --> $DIR/bad-interconversion.rs:30:39
| |
LL | fn result_to_control_flow() -> ControlFlow<String> { LL | fn result_to_control_flow() -> ControlFlow<String> {
| -------------------------------------------------- this function returns a `ControlFlow` | -------------------------------------------------- this function returns a `ControlFlow`
@ -71,7 +71,7 @@ LL | ControlFlow::Continue(Err("hello")?)
= help: for that trait implementation, expected `ControlFlow<String, Infallible>`, found `Result<Infallible, &str>` = help: for that trait implementation, expected `ControlFlow<String, Infallible>`, found `Result<Infallible, &str>`
error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow` error[E0277]: the `?` operator can only be used on `ControlFlow`s in a function that returns `ControlFlow`
--> $DIR/bad-interconversion.rs:37:12 --> $DIR/bad-interconversion.rs:35:12
| |
LL | fn option_to_control_flow() -> ControlFlow<u64> { LL | fn option_to_control_flow() -> ControlFlow<u64> {
| ----------------------------------------------- this function returns a `ControlFlow` | ----------------------------------------------- this function returns a `ControlFlow`
@ -83,7 +83,7 @@ LL | Some(3)?;
= help: for that trait implementation, expected `ControlFlow<u64, Infallible>`, found `Option<Infallible>` = help: for that trait implementation, expected `ControlFlow<u64, Infallible>`, found `Option<Infallible>`
error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type) error[E0277]: the `?` operator in a function that returns `ControlFlow<B, _>` can only be used on other `ControlFlow<B, _>`s (with the same Break type)
--> $DIR/bad-interconversion.rs:43:29 --> $DIR/bad-interconversion.rs:41:29
| |
LL | fn control_flow_to_control_flow() -> ControlFlow<i64> { LL | fn control_flow_to_control_flow() -> ControlFlow<i64> {
| ----------------------------------------------------- this function returns a `ControlFlow` | ----------------------------------------------------- this function returns a `ControlFlow`

View File

@ -1,6 +1,5 @@
//@ run-pass //@ run-pass
#![feature(control_flow_enum)]
#![feature(try_trait_v2)] #![feature(try_trait_v2)]
use std::ops::{ControlFlow, FromResidual, Try}; use std::ops::{ControlFlow, FromResidual, Try};