From fa95f55c6a883c720e369aea697ffbbea6773998 Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Sun, 30 Mar 2025 15:37:00 +0200 Subject: [PATCH 1/2] gio: Rework `glib::ExitCode` for `gio::Application` Add a manual override to use `glib::ExitCode` or `ControlFlow` instead of the gir generated `i32` return value for the `command-line` and `handle-local-options` signals as well as the `local_command_line` virtual function. This reworks the `ExitCode` type to only support `u8` values. The `From` implementation is replaced with a `TryFrom` implementation. --- .github/workflows/CI.yml | 4 +- Cargo.toml | 2 +- README.md | 2 +- cairo/README.md | 2 +- gdk-pixbuf/README.md | 2 +- gio/Gir.toml | 8 ++ gio/README.md | 2 +- gio/src/application.rs | 79 +++++++++++++++++- gio/src/auto/application.rs | 67 +--------------- gio/src/subclass/application.rs | 54 ++++++++----- glib-build-tools/README.md | 2 +- glib/README.md | 2 +- glib/src/exit_code.rs | 80 ++++++++++++++++--- glib/src/lib.rs | 2 +- graphene/README.md | 2 +- pango/README.md | 2 +- pangocairo/README.md | 2 +- .../glib-dependent-dependent/Cargo.toml | 2 +- .../gstreamer/Cargo.toml | 2 +- .../two-levels-glib-dependent/gtk/Cargo.toml | 2 +- 20 files changed, 201 insertions(+), 119 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index a69fab57dbfa..d6ec23465ee7 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -18,7 +18,7 @@ jobs: - stable - beta - nightly - - "1.80.0" + - "1.83.0" conf: - { name: "cairo", features: "png,pdf,svg,ps,use_glib,v1_18,freetype,script,xcb,xlib,win32-surface", nightly: "--features 'png,pdf,svg,ps,use_glib,v1_18,freetype,script,xcb,xlib,win32-surface'", test_sys: true } - { name: "gdk-pixbuf", features: "v2_42", nightly: "--all-features", test_sys: true } @@ -104,7 +104,7 @@ jobs: - stable - beta - nightly - - "1.80.0" + - "1.83.0" steps: - uses: actions/checkout@v4 - uses: actions-rs/toolchain@v1 diff --git a/Cargo.toml b/Cargo.toml index 4a621d3ecff9..cd1d30eb5cc8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ repository = "https://github.com/gtk-rs/gtk-rs-core" license = "MIT" exclude = ["gir-files/*"] edition = "2021" -rust-version = "1.80" +rust-version = "1.83" [workspace.dependencies] libc = "0.2" diff --git a/README.md b/README.md index 239dce14d48b..c0de6bf1029b 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ information about each crate, please refer to their `README.md` file in their di ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Documentation diff --git a/cairo/README.md b/cairo/README.md index 83e5454a3835..ee97c107dd26 100644 --- a/cairo/README.md +++ b/cairo/README.md @@ -8,7 +8,7 @@ Cairo __1.14__ is the lowest supported version for the underlying library. ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Default-on features diff --git a/gdk-pixbuf/README.md b/gdk-pixbuf/README.md index 59cfb09f1718..d2b575992844 100644 --- a/gdk-pixbuf/README.md +++ b/gdk-pixbuf/README.md @@ -6,7 +6,7 @@ GDK-PixBuf __2.36.8__ is the lowest supported version for the underlying library ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Documentation diff --git a/gio/Gir.toml b/gio/Gir.toml index cfa9a751f01c..7369fbb6b181 100644 --- a/gio/Gir.toml +++ b/gio/Gir.toml @@ -310,6 +310,14 @@ generate_builder = true name = "open" manual = true doc_trait_name = "ApplicationExtManual" + [[object.signal]] + name = "command-line" + manual = true + doc_trait_name = "ApplicationExtManual" + [[object.signal]] + name = "handle-local-options" + manual = true + doc_trait_name = "ApplicationExtManual" [[object.function]] name = "run" manual = true diff --git a/gio/README.md b/gio/README.md index 8d6e38442190..6e95f7004b31 100644 --- a/gio/README.md +++ b/gio/README.md @@ -6,7 +6,7 @@ GIO __2.56__ is the lowest supported version for the underlying library. ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Documentation diff --git a/gio/src/application.rs b/gio/src/application.rs index 264ebf590399..030a623a4d53 100644 --- a/gio/src/application.rs +++ b/gio/src/application.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{boxed::Box as Box_, mem::transmute}; +use std::{boxed::Box as Box_, mem::transmute, ops::ControlFlow}; use glib::{ prelude::*, @@ -9,13 +9,14 @@ use glib::{ ExitCode, GString, }; -use crate::{ffi, Application, File}; +use crate::{ffi, Application, ApplicationCommandLine, File}; pub trait ApplicationExtManual: IsA { #[doc(alias = "g_application_run")] fn run(&self) -> ExitCode { self.run_with_args(&std::env::args().collect::>()) } + #[doc(alias = "g_application_run")] fn run_with_args>(&self, args: &[S]) -> ExitCode { let argv: Vec<&str> = args.iter().map(|a| a.as_ref()).collect(); @@ -23,8 +24,10 @@ pub trait ApplicationExtManual: IsA { let exit_code = unsafe { ffi::g_application_run(self.as_ref().to_glib_none().0, argc, argv.to_glib_none().0) }; - ExitCode::from(exit_code) + ExitCode::try_from(exit_code).unwrap() } + + #[doc(alias = "open")] fn connect_open(&self, f: F) -> SignalHandlerId { unsafe extern "C" fn open_trampoline( this: *mut ffi::GApplication, @@ -56,6 +59,76 @@ pub trait ApplicationExtManual: IsA { } } + #[doc(alias = "command-line")] + fn connect_command_line ExitCode + 'static>( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn command_line_trampoline< + P: IsA, + F: Fn(&P, &ApplicationCommandLine) -> ExitCode + 'static, + >( + this: *mut ffi::GApplication, + command_line: *mut ffi::GApplicationCommandLine, + f: glib::ffi::gpointer, + ) -> std::ffi::c_int { + let f: &F = &*(f as *const F); + f( + Application::from_glib_borrow(this).unsafe_cast_ref(), + &from_glib_borrow(command_line), + ) + .into() + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + c"command-line".as_ptr() as *const _, + Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>( + command_line_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[doc(alias = "handle-local-options")] + fn connect_handle_local_options< + F: Fn(&Self, &glib::VariantDict) -> ControlFlow + 'static, + >( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn handle_local_options_trampoline< + P: IsA, + F: Fn(&P, &glib::VariantDict) -> ControlFlow + 'static, + >( + this: *mut ffi::GApplication, + options: *mut glib::ffi::GVariantDict, + f: glib::ffi::gpointer, + ) -> std::ffi::c_int { + let f: &F = &*(f as *const F); + f( + Application::from_glib_borrow(this).unsafe_cast_ref(), + &from_glib_borrow(options), + ) + .break_value() + .map(i32::from) + .unwrap_or(-1) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + c"handle-local-options".as_ptr() as *const _, + Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>( + handle_local_options_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + #[doc(alias = "g_application_hold")] fn hold(&self) -> ApplicationHoldGuard { unsafe { diff --git a/gio/src/auto/application.rs b/gio/src/auto/application.rs index 009a68e0eaa4..86908faf9b89 100644 --- a/gio/src/auto/application.rs +++ b/gio/src/auto/application.rs @@ -3,8 +3,7 @@ // DO NOT EDIT use crate::{ - ffi, ActionGroup, ActionMap, ApplicationCommandLine, ApplicationFlags, Cancellable, - DBusConnection, File, Notification, + ffi, ActionGroup, ActionMap, ApplicationFlags, Cancellable, DBusConnection, File, Notification, }; use glib::{ object::ObjectType as _, @@ -464,70 +463,6 @@ pub trait ApplicationExt: IsA + 'static { } } - #[doc(alias = "command-line")] - fn connect_command_line i32 + 'static>( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn command_line_trampoline< - P: IsA, - F: Fn(&P, &ApplicationCommandLine) -> i32 + 'static, - >( - this: *mut ffi::GApplication, - command_line: *mut ffi::GApplicationCommandLine, - f: glib::ffi::gpointer, - ) -> std::ffi::c_int { - let f: &F = &*(f as *const F); - f( - Application::from_glib_borrow(this).unsafe_cast_ref(), - &from_glib_borrow(command_line), - ) - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - c"command-line".as_ptr() as *const _, - Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>( - command_line_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - #[doc(alias = "handle-local-options")] - fn connect_handle_local_options i32 + 'static>( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn handle_local_options_trampoline< - P: IsA, - F: Fn(&P, &glib::VariantDict) -> i32 + 'static, - >( - this: *mut ffi::GApplication, - options: *mut glib::ffi::GVariantDict, - f: glib::ffi::gpointer, - ) -> std::ffi::c_int { - let f: &F = &*(f as *const F); - f( - Application::from_glib_borrow(this).unsafe_cast_ref(), - &from_glib_borrow(options), - ) - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - c"handle-local-options".as_ptr() as *const _, - Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>( - handle_local_options_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - #[cfg(feature = "v2_60")] #[cfg_attr(docsrs, doc(cfg(feature = "v2_60")))] #[doc(alias = "name-lost")] diff --git a/gio/src/subclass/application.rs b/gio/src/subclass/application.rs index 559233edc434..40e0c6752894 100644 --- a/gio/src/subclass/application.rs +++ b/gio/src/subclass/application.rs @@ -1,6 +1,11 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::{ffi::OsString, fmt, ops::Deref, ptr}; +use std::{ + ffi::OsString, + fmt, + ops::{ControlFlow, Deref}, + ptr, +}; use glib::{ prelude::*, subclass::prelude::*, translate::*, Error, ExitCode, Propagation, VariantDict, @@ -85,7 +90,7 @@ pub trait ApplicationImpl: self.parent_command_line(command_line) } - fn local_command_line(&self, arguments: &mut ArgumentList) -> Option { + fn local_command_line(&self, arguments: &mut ArgumentList) -> ControlFlow { self.parent_local_command_line(arguments) } @@ -109,7 +114,7 @@ pub trait ApplicationImpl: self.parent_startup() } - fn handle_local_options(&self, options: &VariantDict) -> ExitCode { + fn handle_local_options(&self, options: &VariantDict) -> ControlFlow { self.parent_handle_local_options(options) } @@ -177,11 +182,12 @@ pub trait ApplicationImplExt: ApplicationImpl { self.obj().unsafe_cast_ref::().to_glib_none().0, command_line.to_glib_none().0, ) - .into() + .try_into() + .unwrap() } } - fn parent_local_command_line(&self, arguments: &mut ArgumentList) -> Option { + fn parent_local_command_line(&self, arguments: &mut ArgumentList) -> ControlFlow { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GApplicationClass; @@ -198,8 +204,8 @@ pub trait ApplicationImplExt: ApplicationImpl { arguments.refresh(); match res { - glib::ffi::GFALSE => None, - _ => Some(exit_status.into()), + glib::ffi::GFALSE => ControlFlow::Continue(()), + _ => ControlFlow::Break(exit_status.try_into().unwrap()), } } } @@ -264,19 +270,22 @@ pub trait ApplicationImplExt: ApplicationImpl { } } - fn parent_handle_local_options(&self, options: &VariantDict) -> ExitCode { + fn parent_handle_local_options(&self, options: &VariantDict) -> ControlFlow { unsafe { let data = Self::type_data(); let parent_class = data.as_ref().parent_class() as *mut ffi::GApplicationClass; if let Some(f) = (*parent_class).handle_local_options { - f( + let ret = f( self.obj().unsafe_cast_ref::().to_glib_none().0, options.to_glib_none().0, - ) - .into() + ); + + match ret { + -1 => ControlFlow::Continue(()), + _ => ControlFlow::Break(ret.try_into().unwrap()), + } } else { - // Continue default handling - ExitCode::from(-1) + ControlFlow::Continue(()) } } } @@ -406,15 +415,15 @@ unsafe extern "C" fn application_local_command_line( let imp = instance.imp(); let mut args = ArgumentList::new(arguments); - let res = imp.local_command_line(&mut args).map(i32::from); + let res = imp.local_command_line(&mut args); args.refresh(); match res { - Some(ret) => { - *exit_status = ret; + ControlFlow::Break(ret) => { + *exit_status = ret.into(); glib::ffi::GTRUE } - None => glib::ffi::GFALSE, + ControlFlow::Continue(()) => glib::ffi::GFALSE, } } unsafe extern "C" fn application_open( @@ -461,7 +470,10 @@ unsafe extern "C" fn application_handle_local_options( let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); - imp.handle_local_options(&from_glib_borrow(options)).into() + imp.handle_local_options(&from_glib_borrow(options)) + .break_value() + .map(i32::from) + .unwrap_or(-1) } unsafe extern "C" fn application_dbus_register( @@ -513,7 +525,7 @@ mod tests { use super::*; use crate::prelude::*; - const EXIT_STATUS: i32 = 20; + const EXIT_STATUS: u8 = 20; mod imp { use super::*; @@ -545,7 +557,7 @@ mod tests { EXIT_STATUS.into() } - fn local_command_line(&self, arguments: &mut ArgumentList) -> Option { + fn local_command_line(&self, arguments: &mut ArgumentList) -> ControlFlow { let mut rm = Vec::new(); for (i, line) in arguments.iter().enumerate() { @@ -562,7 +574,7 @@ mod tests { arguments.remove(*i); } - None + ControlFlow::Continue(()) } } } diff --git a/glib-build-tools/README.md b/glib-build-tools/README.md index 6fcf89e0610a..bf8f20dfdd60 100644 --- a/glib-build-tools/README.md +++ b/glib-build-tools/README.md @@ -4,7 +4,7 @@ Crate containing helpers for building GIO-based applications. ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Documentation diff --git a/glib/README.md b/glib/README.md index 8f611427cf6e..0f2d4cbd627b 100644 --- a/glib/README.md +++ b/glib/README.md @@ -16,7 +16,7 @@ crates. ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Dynamic typing diff --git a/glib/src/exit_code.rs b/glib/src/exit_code.rs index 4a275c9263be..6202b6cafc06 100644 --- a/glib/src/exit_code.rs +++ b/glib/src/exit_code.rs @@ -1,33 +1,87 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use std::process::Termination; - #[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)] -pub struct ExitCode(i32); +pub struct ExitCode(u8); impl ExitCode { - pub const SUCCESS: Self = Self(0); - pub const FAILURE: Self = Self(1); + const MIN: i32 = u8::MIN as i32; + const MAX: i32 = u8::MAX as i32; + + // rustdoc-stripper-ignore-next + /// The canonical ExitCode for successful termination on this platform. + pub const SUCCESS: Self = Self(libc::EXIT_SUCCESS as u8); + + // rustdoc-stripper-ignore-next + /// The canonical ExitCode for unsuccessful termination on this platform. + pub const FAILURE: Self = Self(libc::EXIT_FAILURE as u8); - pub fn value(&self) -> i32 { + pub const fn new(code: u8) -> Self { + Self(code) + } + + pub const fn get(&self) -> u8 { self.0 } } -impl From for ExitCode { - fn from(value: i32) -> Self { +#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)] +pub struct InvalidExitCode(i32); + +impl InvalidExitCode { + pub const fn new(code: i32) -> Option { + match code { + ExitCode::MIN..=ExitCode::MAX => None, + _ => Some(Self(code)), + } + } + + pub const fn get(&self) -> i32 { + self.0 + } +} + +impl std::fmt::Display for InvalidExitCode { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self(code) = self; + write!(f, "{code} is not a valid glib exit code") + } +} + +impl std::error::Error for InvalidExitCode {} + +impl From for ExitCode { + fn from(value: u8) -> Self { Self(value) } } -impl From for i32 { - fn from(value: ExitCode) -> Self { - value.0 +impl TryFrom for ExitCode { + type Error = InvalidExitCode; + + fn try_from(code: i32) -> Result { + match code { + ExitCode::MIN..=ExitCode::MAX => Ok(Self(code as _)), + _ => Err(InvalidExitCode(code)), + } } } -impl Termination for ExitCode { +macro_rules! impl_from_exit_code_0 { + ($($ty:ty)*) => { + $( + impl From for $ty { + fn from(code: ExitCode) -> Self { + <$ty>::from(code.0) + } + } + )* + }; +} + +impl_from_exit_code_0! { u8 u16 u32 u64 i16 i32 i64 std::process::ExitCode } + +impl std::process::Termination for ExitCode { fn report(self) -> std::process::ExitCode { - std::process::ExitCode::from(self.0 as u8) + self.into() } } diff --git a/glib/src/lib.rs b/glib/src/lib.rs index a4ed600ef0f1..827c49b3fd59 100644 --- a/glib/src/lib.rs +++ b/glib/src/lib.rs @@ -117,7 +117,7 @@ pub mod object; mod boxed_any_object; pub use boxed_any_object::BoxedAnyObject; mod exit_code; -pub use exit_code::ExitCode; +pub use exit_code::{ExitCode, InvalidExitCode}; pub mod collections; pub use collections::{List, PtrSlice, SList, Slice, StrV}; diff --git a/graphene/README.md b/graphene/README.md index c6b75fe51f41..f310ab1c1d15 100644 --- a/graphene/README.md +++ b/graphene/README.md @@ -6,7 +6,7 @@ Graphene __1.10__ is the lowest supported version for the underlying library. ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Documentation diff --git a/pango/README.md b/pango/README.md index bbcec65d65c7..20cca3a6d30d 100644 --- a/pango/README.md +++ b/pango/README.md @@ -6,7 +6,7 @@ Pango __1.40__ is the lowest supported version for the underlying library. ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Documentation diff --git a/pangocairo/README.md b/pangocairo/README.md index 7c2d66a17d70..3f6124cae4ac 100644 --- a/pangocairo/README.md +++ b/pangocairo/README.md @@ -7,7 +7,7 @@ PangoCairo __1.40__ is the lowest supported version for the underlying library. ## Minimum supported Rust version -Currently, the minimum supported Rust version is `1.80.0`. +Currently, the minimum supported Rust version is `1.83.0`. ## Documentation diff --git a/tests/two-levels-glib-dependent/glib-dependent-dependent/Cargo.toml b/tests/two-levels-glib-dependent/glib-dependent-dependent/Cargo.toml index d3030c357c77..524c25c4abf0 100644 --- a/tests/two-levels-glib-dependent/glib-dependent-dependent/Cargo.toml +++ b/tests/two-levels-glib-dependent/glib-dependent-dependent/Cargo.toml @@ -6,7 +6,7 @@ description = "crate that depends on a glib-rs dependent crate for validation of keywords = ["gtk-rs-core", "integration"] license = "MIT/Apache-2.0" edition = "2021" -rust-version = "1.80" +rust-version = "1.83" [dependencies] # Use `gstreamer` as a simulation of an identified crate re-exporting `glib`. diff --git a/tests/two-levels-glib-dependent/gstreamer/Cargo.toml b/tests/two-levels-glib-dependent/gstreamer/Cargo.toml index 338349a8bec5..86ae3c55526a 100644 --- a/tests/two-levels-glib-dependent/gstreamer/Cargo.toml +++ b/tests/two-levels-glib-dependent/gstreamer/Cargo.toml @@ -7,7 +7,7 @@ description = "gstreamer simulator as a glib dependent crate for validation of g keywords = ["gtk-rs-core", "integration"] license = "MIT/Apache-2.0" edition = "2021" -rust-version = "1.80" +rust-version = "1.83" [dependencies] glib = { path = "../../../glib" } diff --git a/tests/two-levels-glib-dependent/gtk/Cargo.toml b/tests/two-levels-glib-dependent/gtk/Cargo.toml index ed0cf601795e..d57b6469c936 100644 --- a/tests/two-levels-glib-dependent/gtk/Cargo.toml +++ b/tests/two-levels-glib-dependent/gtk/Cargo.toml @@ -7,7 +7,7 @@ description = "gtk simulator as a glib dependent crate for validation of glib re keywords = ["gtk-rs-core", "integration"] license = "MIT/Apache-2.0" edition = "2021" -rust-version = "1.80" +rust-version = "1.83" [dependencies] glib = { path = "../../../glib" } From 218ed478de31614205b8af0790461d43ce4c122b Mon Sep 17 00:00:00 2001 From: Philipp Jungkamp Date: Tue, 8 Apr 2025 12:42:10 +0200 Subject: [PATCH 2/2] Replace `map_or` with `is_none_or` to satisfy clippy --- gio/src/gio_future.rs | 2 +- glib/src/source_futures.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gio/src/gio_future.rs b/gio/src/gio_future.rs index 7560e3a5b20a..114c7dd3e94d 100644 --- a/gio/src/gio_future.rs +++ b/gio/src/gio_future.rs @@ -115,7 +115,7 @@ where && self .receiver .as_ref() - .map_or(true, |receiver| receiver.is_terminated()) + .is_none_or(|receiver| receiver.is_terminated()) } } diff --git a/glib/src/source_futures.rs b/glib/src/source_futures.rs index c3140fd28a1d..dd719d84be6e 100644 --- a/glib/src/source_futures.rs +++ b/glib/src/source_futures.rs @@ -101,7 +101,7 @@ where && self .source .as_ref() - .map_or(true, |(_, receiver)| receiver.is_terminated()) + .is_none_or(|(_, receiver)| receiver.is_terminated()) } } @@ -313,7 +313,7 @@ where && self .source .as_ref() - .map_or(true, |(_, receiver)| receiver.is_terminated()) + .is_none_or(|(_, receiver)| receiver.is_terminated()) } }