From e03b060ca12eabb6d121160c831152e0690cb7fd Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 3 Sep 2023 18:04:39 +0200 Subject: [PATCH] Add public EncodeReturn, EncodeArgument and EncodeArguments And make the two conversion traits ConvertReturn and ConvertArgument in a sense "more" private --- crates/block2/src/block.rs | 7 +- crates/block2/src/concrete_block.rs | 10 +- crates/block2/src/global.rs | 2 +- crates/objc2/CHANGELOG.md | 6 + crates/objc2/src/__macro_helpers/convert.rs | 168 +++++++++++ crates/objc2/src/__macro_helpers/mod.rs | 7 +- .../src/{rc => __macro_helpers}/writeback.rs | 10 +- crates/objc2/src/declare/mod.rs | 15 +- crates/objc2/src/{encode/mod.rs => encode.rs} | 152 +++++++++- crates/objc2/src/encode/__unstable.rs | 283 ------------------ crates/objc2/src/macros/declare_class.rs | 16 +- crates/objc2/src/message/apple/arm.rs | 3 +- crates/objc2/src/message/apple/arm64.rs | 2 +- crates/objc2/src/message/apple/mod.rs | 2 +- crates/objc2/src/message/apple/x86.rs | 3 +- crates/objc2/src/message/apple/x86_64.rs | 3 +- crates/objc2/src/message/gnustep.rs | 2 +- crates/objc2/src/message/mod.rs | 68 +++-- crates/objc2/src/rc/mod.rs | 1 - crates/objc2/src/runtime/bool.rs | 10 +- crates/objc2/src/runtime/mod.rs | 13 +- crates/test-ui/ui/add_method_no_bool.stderr | 1 + .../ui/declare_class_invalid_type.stderr | 42 ++- .../ui/extern_methods_invalid_type.stderr | 18 +- .../test-ui/ui/global_block_not_encode.stderr | 1 + .../ui/invalid_option_encode_impl.stderr | 4 +- .../ui/invalid_option_encode_impl_ref.stderr | 4 +- crates/test-ui/ui/msg_send_not_encode.stderr | 12 +- crates/test-ui/ui/not_encode.stderr | 1 + crates/test-ui/ui/not_writeback.stderr | 21 +- 30 files changed, 476 insertions(+), 411 deletions(-) create mode 100644 crates/objc2/src/__macro_helpers/convert.rs rename crates/objc2/src/{rc => __macro_helpers}/writeback.rs (97%) rename crates/objc2/src/{encode/mod.rs => encode.rs} (83%) delete mode 100644 crates/objc2/src/encode/__unstable.rs diff --git a/crates/block2/src/block.rs b/crates/block2/src/block.rs index 0b32ad489..00c38cdcf 100644 --- a/crates/block2/src/block.rs +++ b/crates/block2/src/block.rs @@ -1,15 +1,14 @@ use core::marker::PhantomData; use core::mem; -use objc2::encode::__unstable::EncodeReturn; -use objc2::encode::{Encode, Encoding, RefEncode}; +use objc2::encode::{EncodeArgument, EncodeReturn, Encoding, RefEncode}; use crate::ffi; /// Types that may be used as the arguments of an Objective-C block. /// /// This is implemented for tuples of up to 12 arguments, where each argument -/// implements [`Encode`]. +/// implements [`EncodeArgument`]. /// /// /// # Safety @@ -28,7 +27,7 @@ pub unsafe trait BlockArguments: Sized { macro_rules! block_args_impl { ($($a:ident: $t:ident),*) => ( - unsafe impl<$($t: Encode),*> BlockArguments for ($($t,)*) { + unsafe impl<$($t: EncodeArgument),*> BlockArguments for ($($t,)*) { #[inline] unsafe fn __call_block( invoke: unsafe extern "C" fn(), diff --git a/crates/block2/src/concrete_block.rs b/crates/block2/src/concrete_block.rs index 88f566205..9c9542bf9 100644 --- a/crates/block2/src/concrete_block.rs +++ b/crates/block2/src/concrete_block.rs @@ -5,8 +5,7 @@ use core::ops::Deref; use core::ptr; use std::os::raw::c_ulong; -use objc2::encode::__unstable::EncodeReturn; -use objc2::encode::{Encode, Encoding, RefEncode}; +use objc2::encode::{EncodeArgument, EncodeReturn, Encoding, RefEncode}; use crate::{ffi, Block, BlockArguments, RcBlock}; @@ -17,7 +16,8 @@ mod private { /// Types that may be converted into a [`ConcreteBlock`]. /// /// This is implemented for [`Fn`] closures of up to 12 arguments, where each -/// argument and the return type implements [`Encode`]. +/// argument implements [`EncodeArgument`] and the return type implements +/// [`EncodeReturn`]. /// /// /// # Safety @@ -37,12 +37,12 @@ macro_rules! concrete_block_impl { concrete_block_impl!($f,); ); ($f:ident, $($a:ident : $t:ident),*) => ( - impl<$($t: Encode,)* R: EncodeReturn, X> private::Sealed<($($t,)*)> for X + impl<$($t: EncodeArgument,)* R: EncodeReturn, X> private::Sealed<($($t,)*)> for X where X: Fn($($t,)*) -> R, {} - unsafe impl<$($t: Encode,)* R: EncodeReturn, X> IntoConcreteBlock<($($t,)*)> for X + unsafe impl<$($t: EncodeArgument,)* R: EncodeReturn, X> IntoConcreteBlock<($($t,)*)> for X where X: Fn($($t,)*) -> R, { diff --git a/crates/block2/src/global.rs b/crates/block2/src/global.rs index 3851e045c..f016301b1 100644 --- a/crates/block2/src/global.rs +++ b/crates/block2/src/global.rs @@ -5,7 +5,7 @@ use core::ops::Deref; use core::ptr; use std::os::raw::c_ulong; -use objc2::encode::__unstable::EncodeReturn; +use objc2::encode::EncodeReturn; use super::{ffi, Block}; use crate::BlockArguments; diff --git a/crates/objc2/CHANGELOG.md b/crates/objc2/CHANGELOG.md index 67c7d90da..379aeac26 100644 --- a/crates/objc2/CHANGELOG.md +++ b/crates/objc2/CHANGELOG.md @@ -8,6 +8,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added * Added `mutability::IsMainThreadOnly`. +* Added new `encode` traits `EncodeReturn`, `EncodeArgument` and + `EncodeArguments`. + +### Changed +* **BREAKING**: `AnyClass::verify_sel` now take more well-defined types + `EncodeArguments` and `EncodeReturn`. ## 0.4.1 - 2023-07-31 diff --git a/crates/objc2/src/__macro_helpers/convert.rs b/crates/objc2/src/__macro_helpers/convert.rs new file mode 100644 index 000000000..19bc38ea5 --- /dev/null +++ b/crates/objc2/src/__macro_helpers/convert.rs @@ -0,0 +1,168 @@ +use crate::encode::{EncodeArgument, EncodeReturn}; +use crate::rc::Id; +use crate::runtime::Bool; +use crate::Message; + +mod argument_private { + pub trait Sealed {} +} + +/// Represents types that can be converted to/from an [`EncodeArgument`] type. +/// +/// This is implemented specially for [`bool`] to allow using that as +/// Objective-C `BOOL`, where it would otherwise not be allowed (since they +/// are not ABI compatible). +/// +/// This is also done specially for `&mut Id<_>`-like arguments, to allow +/// using those as "out" parameters. +pub trait ConvertArgument: argument_private::Sealed { + /// The inner type that this can be converted to and from. + #[doc(hidden)] + type __Inner: EncodeArgument; + + /// A helper type for out parameters. + #[doc(hidden)] + type __StoredBeforeMessage: Sized; + + #[doc(hidden)] + fn __from_declared_param(inner: Self::__Inner) -> Self; + + #[doc(hidden)] + fn __into_argument(self) -> (Self::__Inner, Self::__StoredBeforeMessage); + + #[doc(hidden)] + unsafe fn __process_after_message_send(_stored: Self::__StoredBeforeMessage) {} +} + +// Implemented in writeback.rs +impl argument_private::Sealed for &mut Id {} +impl argument_private::Sealed for Option<&mut Id> {} +impl argument_private::Sealed for &mut Option> {} +impl argument_private::Sealed for Option<&mut Option>> {} + +impl argument_private::Sealed for T {} +impl ConvertArgument for T { + type __Inner = Self; + + type __StoredBeforeMessage = (); + + #[inline] + fn __from_declared_param(inner: Self::__Inner) -> Self { + inner + } + + #[inline] + fn __into_argument(self) -> (Self::__Inner, Self::__StoredBeforeMessage) { + (self, ()) + } +} + +impl argument_private::Sealed for bool {} +impl ConvertArgument for bool { + type __Inner = Bool; + + type __StoredBeforeMessage = (); + + #[inline] + fn __from_declared_param(inner: Self::__Inner) -> Self { + inner.as_bool() + } + + #[inline] + fn __into_argument(self) -> (Self::__Inner, Self::__StoredBeforeMessage) { + (Bool::new(self), ()) + } +} + +mod return_private { + pub trait Sealed {} +} + +/// Same as [`ConvertArgument`], but for return types. +pub trait ConvertReturn: return_private::Sealed { + /// The inner type that this can be converted to and from. + #[doc(hidden)] + type __Inner: EncodeReturn; + + #[doc(hidden)] + fn __into_declared_return(self) -> Self::__Inner; + + #[doc(hidden)] + fn __from_return(inner: Self::__Inner) -> Self; +} + +impl return_private::Sealed for T {} +impl ConvertReturn for T { + type __Inner = Self; + + #[inline] + fn __into_declared_return(self) -> Self::__Inner { + self + } + + #[inline] + fn __from_return(inner: Self::__Inner) -> Self { + inner + } +} + +impl return_private::Sealed for bool {} +impl ConvertReturn for bool { + type __Inner = Bool; + + #[inline] + fn __into_declared_return(self) -> Self::__Inner { + Bool::new(self) + } + + #[inline] + fn __from_return(inner: Self::__Inner) -> Self { + inner.as_bool() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use core::any::TypeId; + + #[test] + fn convert_normally_noop() { + assert_eq!( + TypeId::of::<::__Inner>(), + TypeId::of::() + ); + assert_eq!(::__from_declared_param(42), 42); + assert_eq!(ConvertArgument::__into_argument(42i32).0, 42); + } + + #[test] + fn convert_i8() { + assert_eq!( + TypeId::of::<::__Inner>(), + TypeId::of::() + ); + assert_eq!(::__from_declared_param(-3), -3); + assert_eq!(ConvertArgument::__into_argument(-3i32).0, -3); + } + + #[test] + fn convert_bool() { + assert!(!::__from_declared_param(Bool::NO)); + assert!(::__from_declared_param(Bool::YES)); + assert!(!::__from_return(Bool::NO)); + assert!(::__from_return(Bool::YES)); + + assert!(!ConvertArgument::__into_argument(false).0.as_bool()); + assert!(ConvertArgument::__into_argument(true).0.as_bool()); + assert!(!ConvertReturn::__into_declared_return(false).as_bool()); + assert!(ConvertReturn::__into_declared_return(true).as_bool()); + + #[cfg(all(feature = "apple", target_os = "macos", target_arch = "x86_64"))] + assert_eq!( + ::__Inner::ENCODING_ARGUMENT, + crate::encode::Encoding::Char, + ); + } +} diff --git a/crates/objc2/src/__macro_helpers/mod.rs b/crates/objc2/src/__macro_helpers/mod.rs index b03753df9..0ffdf610e 100644 --- a/crates/objc2/src/__macro_helpers/mod.rs +++ b/crates/objc2/src/__macro_helpers/mod.rs @@ -29,7 +29,9 @@ pub use std::sync::Once; mod cache; mod common_selectors; +mod convert; mod declare_class; +mod writeback; pub use self::cache::{CachedClass, CachedSel}; pub use self::common_selectors::{alloc_sel, dealloc_sel, init_sel, new_sel}; @@ -37,6 +39,7 @@ pub use self::declare_class::{ assert_mutability_matches_superclass_mutability, MaybeOptionId, MessageRecieveId, ValidSubclassMutability, }; +pub use convert::{ConvertArgument, ConvertReturn}; /// Helper for specifying the retain semantics for a given selector family. /// @@ -125,8 +128,8 @@ pub trait MsgSendId { } else { // In this case, the error has very likely been created, but has // been autoreleased (as is common for "out parameters", see - // `src/rc/writeback.rs`). Hence we need to retain it if we want - // it to live across autorelease pools. + // `src/__macro_helpers/writeback.rs`). Hence we need to retain it + // if we want it to live across autorelease pools. // // SAFETY: The message send is guaranteed to populate the error // object, or leave it as NULL. The error is shared, and all diff --git a/crates/objc2/src/rc/writeback.rs b/crates/objc2/src/__macro_helpers/writeback.rs similarity index 97% rename from crates/objc2/src/rc/writeback.rs rename to crates/objc2/src/__macro_helpers/writeback.rs index a972fe3b6..3b4e78f77 100644 --- a/crates/objc2/src/rc/writeback.rs +++ b/crates/objc2/src/__macro_helpers/writeback.rs @@ -10,13 +10,13 @@ use core::mem::ManuallyDrop; use core::ptr::NonNull; -use crate::encode::__unstable::EncodeConvertArgument; +use super::ConvertArgument; use crate::rc::Id; use crate::Message; // Note the `'static` bound here - this may not be necessary, but I'm unsure // of the exact requirements, so we better keep it for now. -impl EncodeConvertArgument for &mut Id { +impl ConvertArgument for &mut Id { // We use `*mut T` as the inner value instead of `NonNull`, since we // want to do debug checking that the value hasn't unexpectedly been // overwritten to contain NULL (which is clear UB, but the user might have @@ -109,7 +109,7 @@ impl EncodeConvertArgument for &mut Id { } } -impl EncodeConvertArgument for &mut Option> { +impl ConvertArgument for &mut Option> { type __Inner = NonNull<*mut T>; type __StoredBeforeMessage = (Self::__Inner, *mut T); @@ -156,7 +156,7 @@ impl EncodeConvertArgument for &mut Option> { // known at compile-time, and for the `None` case it would be detrimental to // have extra `retain/release` calls here. -impl EncodeConvertArgument for Option<&mut Id> { +impl ConvertArgument for Option<&mut Id> { type __Inner = Option>; type __StoredBeforeMessage = Option<(NonNull<*mut T>, NonNull)>; @@ -185,7 +185,7 @@ impl EncodeConvertArgument for Option<&mut Id> { } } -impl EncodeConvertArgument for Option<&mut Option>> { +impl ConvertArgument for Option<&mut Option>> { type __Inner = Option>; type __StoredBeforeMessage = Option<(NonNull<*mut T>, *mut T)>; diff --git a/crates/objc2/src/declare/mod.rs b/crates/objc2/src/declare/mod.rs index 97088959f..2dd45eb60 100644 --- a/crates/objc2/src/declare/mod.rs +++ b/crates/objc2/src/declare/mod.rs @@ -131,8 +131,7 @@ use core::ptr; use core::ptr::NonNull; use std::ffi::CString; -use crate::encode::__unstable::{EncodeArguments, EncodeReturn}; -use crate::encode::{Encode, Encoding, RefEncode}; +use crate::encode::{Encode, EncodeArgument, EncodeArguments, EncodeReturn, Encoding, RefEncode}; use crate::ffi; use crate::mutability::IsMutable; use crate::rc::Allocated; @@ -171,14 +170,14 @@ macro_rules! method_decl_impl { where T: ?Sized + $t_bound, $r: EncodeReturn, - $($t: Encode,)* + $($t: EncodeArgument,)* {} impl<$($l,)* T, $r, $($t),*> MethodImplementation for $f where T: ?Sized + $t_bound, $r: EncodeReturn, - $($t: Encode,)* + $($t: EncodeArgument,)* { type Callee = T; type Ret = $r; @@ -193,13 +192,13 @@ macro_rules! method_decl_impl { impl<$($l,)* $r, $($t),*> private::Sealed for $f where $r: EncodeReturn, - $($t: Encode,)* + $($t: EncodeArgument,)* {} impl<$($l,)* $r, $($t),*> MethodImplementation for $f where $r: EncodeReturn, - $($t: Encode,)* + $($t: EncodeArgument,)* { type Callee = $callee; type Ret = $r; @@ -215,14 +214,14 @@ macro_rules! method_decl_impl { impl private::Sealed for $f where T: ?Sized + Message, - $($t: Encode,)* + $($t: EncodeArgument,)* {} #[doc(hidden)] impl MethodImplementation for $f where T: ?Sized + Message, - $($t: Encode,)* + $($t: EncodeArgument,)* { type Callee = T; type Ret = __IdReturnValue; diff --git a/crates/objc2/src/encode/mod.rs b/crates/objc2/src/encode.rs similarity index 83% rename from crates/objc2/src/encode/mod.rs rename to crates/objc2/src/encode.rs index 4cdf1d46c..7dcc4c447 100644 --- a/crates/objc2/src/encode/mod.rs +++ b/crates/objc2/src/encode.rs @@ -49,26 +49,26 @@ //! mostly for demonstration. //! //! ``` -#![doc = include_str!("../../examples/encode_core_graphics.rs")] +#![doc = include_str!("../examples/encode_core_graphics.rs")] //! ``` //! //! Implementing [`Encode`] and [`RefEncode`] for a transparent newtype. //! //! ``` -#![doc = include_str!("../../examples/encode_nsuinteger.rs")] +#![doc = include_str!("../examples/encode_nsuinteger.rs")] //! ``` //! //! Implementing [`RefEncode`] for an object, in this case `NSString`. //! //! ``` -#![doc = include_str!("../../examples/encode_nsstring.rs")] +#![doc = include_str!("../examples/encode_nsstring.rs")] //! ``` //! //! Implementing [`RefEncode`] for a type where you don't necessarily know //! about the exact internals / the internals are not representable in Rust. //! //! ``` -#![doc = include_str!("../../examples/encode_opaque_type.rs")] +#![doc = include_str!("../examples/encode_opaque_type.rs")] //! ``` use core::cell::{Cell, UnsafeCell}; @@ -81,9 +81,6 @@ use core::num::{ use core::ptr::NonNull; use core::sync::atomic; -// Intentionally not `#[doc(hidden)]` -pub mod __unstable; - #[doc(inline)] pub use objc2_encode::{Encoding, EncodingBox, ParseError}; @@ -289,6 +286,123 @@ unsafe impl RefEncode for Option { }; } +mod return_private { + pub trait Sealed {} +} + +/// Types that are safe as the return value from Objective-C. +/// +/// This is a sealed trait, and should not need to be implemented manually. +/// +/// +/// # Safety +/// +/// Similar to [`Encode`], except the value is only guaranteed to be valid as +/// a return value, both from functions/methods you're calling, and from +/// declared functions/methods. +/// +/// It does not have to be valid as e.g. an instance variable, or as an +/// argument to a function. +pub unsafe trait EncodeReturn: return_private::Sealed { + /// The Objective-C type-encoding for this type. + const ENCODING_RETURN: Encoding; +} + +impl return_private::Sealed for () {} +// SAFETY: `()` is the same as C's `void` type, which is a valid return type +unsafe impl EncodeReturn for () { + const ENCODING_RETURN: Encoding = Encoding::Void; +} + +impl return_private::Sealed for T {} +// SAFETY: All `Encode` types are also valid as return types +unsafe impl EncodeReturn for T { + const ENCODING_RETURN: Encoding = T::ENCODING; +} + +mod argument_private { + pub trait Sealed {} +} + +/// Types that are safe as arguments to Objective-C methods. +/// +/// This is a sealed trait, and should not need to be implemented manually. +/// +/// +/// # Safety +/// +/// Similar to [`Encode`], except the value is only guaranteed to be valid as +/// an argument or a parameter, both from functions/methods you're calling and +/// from declared functions/methods. +/// +/// It does not have to be valid as e.g. an instance variable, or as an +/// argument to a function. +// +// Note: This is mostly implemented for consistency; there are (not that I've +// found at least) no places where this is not just `Encode`. +// +// You might be tempted to think that `bool` could work in this, but that +// would be a mistake (even ignoring that its size is different on certain +// targets) because it cannot be safely used in declared methods. +pub unsafe trait EncodeArgument: argument_private::Sealed { + /// The Objective-C type-encoding for this type. + const ENCODING_ARGUMENT: Encoding; +} + +impl argument_private::Sealed for T {} +// SAFETY: All `Encode` types are also valid as argument types +unsafe impl EncodeArgument for T { + const ENCODING_ARGUMENT: Encoding = T::ENCODING; +} + +mod args_private { + pub trait Sealed {} +} + +/// Types that represent an ordered group of function arguments, where each +/// argument has an Objective-C type-encoding, or can be converted from one. +/// +/// This is implemented for tuples of up to 16 arguments, where each argument +/// implements [`EncodeArgument`]. It is primarily used to make generic +/// code a bit easier. +/// +/// Note that tuples themselves don't implement [`Encode`] directly, because +/// they're not FFI-safe! +pub trait EncodeArguments: args_private::Sealed { + /// The encodings for the arguments. + const ENCODINGS: &'static [Encoding]; +} + +macro_rules! encode_args_impl { + ($($Arg: ident),*) => { + impl<$($Arg: EncodeArgument),*> args_private::Sealed for ($($Arg,)*) {} + + impl<$($Arg: EncodeArgument),*> EncodeArguments for ($($Arg,)*) { + const ENCODINGS: &'static [Encoding] = &[ + $($Arg::ENCODING_ARGUMENT),* + ]; + } + }; +} + +encode_args_impl!(); +encode_args_impl!(A); +encode_args_impl!(A, B); +encode_args_impl!(A, B, C); +encode_args_impl!(A, B, C, D); +encode_args_impl!(A, B, C, D, E); +encode_args_impl!(A, B, C, D, E, F); +encode_args_impl!(A, B, C, D, E, F, G); +encode_args_impl!(A, B, C, D, E, F, G, H); +encode_args_impl!(A, B, C, D, E, F, G, H, I); +encode_args_impl!(A, B, C, D, E, F, G, H, I, J); +encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K); +encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L); +encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M); +encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N); +encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); +encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); + // TODO: Implement for `PhantomData` and `PhantomPinned`? /// Helper for implementing [`Encode`]. @@ -602,14 +716,14 @@ unsafe impl OptionEncode for NonNull {} /// and return items with a known size. macro_rules! encode_fn_pointer_impl { (@ $FnTy: ty, $($Arg: ident),*) => { - unsafe impl Encode for $FnTy { + unsafe impl Encode for $FnTy { const ENCODING: Encoding = Encoding::Pointer(&Encoding::Unknown); } - unsafe impl RefEncode for $FnTy { + unsafe impl RefEncode for $FnTy { const ENCODING_REF: Encoding = Encoding::Pointer(&Self::ENCODING); } // SAFETY: Function pointers have a NULL niche - unsafe impl OptionEncode for $FnTy {} + unsafe impl OptionEncode for $FnTy {} }; (# $abi:literal; $($Arg: ident),+) => { // Normal functions @@ -768,4 +882,22 @@ mod tests { impls_encode(my_fn3 as extern "C" fn(_) -> _); impls_encode(my_fn4 as extern "C" fn(_, _) -> _); } + + #[test] + fn test_return() { + assert_eq!(::ENCODING_RETURN, ::ENCODING); + assert_eq!(<()>::ENCODING_RETURN, Encoding::Void); + } + + #[test] + fn test_argument() { + assert_eq!(::ENCODING_ARGUMENT, ::ENCODING); + } + + #[test] + fn test_arguments() { + assert!(<()>::ENCODINGS.is_empty()); + assert_eq!(<(i8,)>::ENCODINGS, &[i8::ENCODING]); + assert_eq!(<(i8, u32)>::ENCODINGS, &[i8::ENCODING, u32::ENCODING]); + } } diff --git a/crates/objc2/src/encode/__unstable.rs b/crates/objc2/src/encode/__unstable.rs deleted file mode 100644 index 52f0e901c..000000000 --- a/crates/objc2/src/encode/__unstable.rs +++ /dev/null @@ -1,283 +0,0 @@ -//! # Unstable encoding traits. -//! -//! The traits in this module are unstable, meaning that they are **outside -//! the usual SemVer guarantee**, and may freely change or be removed in patch -//! versions. -//! -//! They are provided here mostly for documentation purposes (e.g. you can -//! check [`EncodeReturn`] to see which types are possible as the return value -//! of a function pointer). -//! -//! If you would like to use some of these, please [open an issue], then we -//! can discuss making them stable. -//! -//! [open an issue]: https://github.com/madsmtm/objc2/issues/new -#![cfg_attr( - feature = "unstable-docsrs", - doc(cfg(feature = "unstable-encode-internals")) -)] - -use crate::encode::{Encode, Encoding}; -use crate::rc::Id; -use crate::runtime::Bool; -use crate::Message; - -mod return_private { - pub trait Sealed {} -} - -/// Types that are safe as the return value from Objective-C. -/// -/// We currently don't need a similar `EncodeArgument` trait, but we might in -/// the future. -/// -/// -/// # Safety -/// -/// Similar to [`Encode`]. -// -// Note: While this is not public, it is still a breaking change to change, -// since `block2` relies on it. -pub unsafe trait EncodeReturn: return_private::Sealed { - /// The Objective-C type-encoding for this type. - const ENCODING_RETURN: Encoding; -} - -impl return_private::Sealed for () {} -unsafe impl EncodeReturn for () { - const ENCODING_RETURN: Encoding = Encoding::Void; -} - -impl return_private::Sealed for T {} -unsafe impl EncodeReturn for T { - const ENCODING_RETURN: Encoding = T::ENCODING; -} - -mod convert_private { - pub trait Sealed {} -} - -impl convert_private::Sealed for T {} -impl convert_private::Sealed for bool {} - -// Implemented in rc/writeback.rs -impl convert_private::Sealed for &mut Id {} -impl convert_private::Sealed for Option<&mut Id> {} -impl convert_private::Sealed for &mut Option> {} -impl convert_private::Sealed for Option<&mut Option>> {} - -/// Represents types that can be converted to/from an [`Encode`] type. -/// -/// This is implemented specially for [`bool`] to allow using that as -/// Objective-C `BOOL`, where it would otherwise not be allowed (since they -/// are not ABI compatible). -/// -/// This is also done specially for `&mut Id<_>`-like arguments, to allow -/// using those as "out" parameters. -pub trait EncodeConvertArgument: convert_private::Sealed { - /// The inner type that this can be converted to and from. - #[doc(hidden)] - type __Inner: Encode; - - /// A helper type for out parameters. - #[doc(hidden)] - type __StoredBeforeMessage: Sized; - - #[doc(hidden)] - fn __from_declared_param(inner: Self::__Inner) -> Self; - - #[doc(hidden)] - fn __into_argument(self) -> (Self::__Inner, Self::__StoredBeforeMessage); - - #[doc(hidden)] - unsafe fn __process_after_message_send(_stored: Self::__StoredBeforeMessage) {} -} - -/// Same as [`EncodeConvertArgument`], but for return types. -pub trait EncodeConvertReturn: convert_private::Sealed { - /// The inner type that this can be converted to and from. - #[doc(hidden)] - type __Inner: EncodeReturn; - - #[doc(hidden)] - fn __into_declared_return(self) -> Self::__Inner; - - #[doc(hidden)] - fn __from_return(inner: Self::__Inner) -> Self; -} - -impl EncodeConvertArgument for T { - type __Inner = Self; - - type __StoredBeforeMessage = (); - - #[inline] - fn __from_declared_param(inner: Self::__Inner) -> Self { - inner - } - - #[inline] - fn __into_argument(self) -> (Self::__Inner, Self::__StoredBeforeMessage) { - (self, ()) - } -} - -impl EncodeConvertReturn for T { - type __Inner = Self; - - #[inline] - fn __into_declared_return(self) -> Self::__Inner { - self - } - - #[inline] - fn __from_return(inner: Self::__Inner) -> Self { - inner - } -} - -impl EncodeConvertArgument for bool { - type __Inner = Bool; - - type __StoredBeforeMessage = (); - - #[inline] - fn __from_declared_param(inner: Self::__Inner) -> Self { - inner.as_bool() - } - - #[inline] - fn __into_argument(self) -> (Self::__Inner, Self::__StoredBeforeMessage) { - (Bool::new(self), ()) - } -} - -impl EncodeConvertReturn for bool { - type __Inner = Bool; - - #[inline] - fn __into_declared_return(self) -> Self::__Inner { - Bool::new(self) - } - - #[inline] - fn __from_return(inner: Self::__Inner) -> Self { - inner.as_bool() - } -} - -mod args_private { - pub trait Sealed {} -} - -/// Types that represent an ordered group of function arguments, where each -/// argument has an Objective-C type-encoding, or can be converted from one. -/// -/// This is implemented for tuples of up to 16 arguments, where each argument -/// implements [`EncodeConvertArgument`]. It is primarily used to make generic -/// code a bit easier. -/// -/// Note that tuples themselves don't implement [`Encode`] directly, because -/// they're not FFI-safe! -pub trait EncodeArguments: args_private::Sealed { - /// The encodings for the arguments. - const ENCODINGS: &'static [Encoding]; -} - -macro_rules! encode_args_impl { - ($($Arg: ident),*) => { - impl<$($Arg: EncodeConvertArgument),*> args_private::Sealed for ($($Arg,)*) {} - - impl<$($Arg: EncodeConvertArgument),*> EncodeArguments for ($($Arg,)*) { - const ENCODINGS: &'static [Encoding] = &[ - // T::__Inner::ENCODING => T::ENCODING - // bool::__Inner::ENCODING => Bool::ENCODING - $($Arg::__Inner::ENCODING),* - ]; - } - }; -} - -encode_args_impl!(); -encode_args_impl!(A); -encode_args_impl!(A, B); -encode_args_impl!(A, B, C); -encode_args_impl!(A, B, C, D); -encode_args_impl!(A, B, C, D, E); -encode_args_impl!(A, B, C, D, E, F); -encode_args_impl!(A, B, C, D, E, F, G); -encode_args_impl!(A, B, C, D, E, F, G, H); -encode_args_impl!(A, B, C, D, E, F, G, H, I); -encode_args_impl!(A, B, C, D, E, F, G, H, I, J); -encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K); -encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L); -encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M); -encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N); -encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); -encode_args_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); - -#[cfg(test)] -mod tests { - use super::*; - - use core::any::TypeId; - - #[test] - fn test_return() { - assert_eq!(::ENCODING_RETURN, ::ENCODING); - assert_eq!(<()>::ENCODING_RETURN, Encoding::Void); - } - - #[test] - fn convert_normally_noop() { - assert_eq!( - TypeId::of::<::__Inner>(), - TypeId::of::() - ); - assert_eq!( - ::__from_declared_param(42), - 42 - ); - assert_eq!(EncodeConvertArgument::__into_argument(42i32).0, 42); - } - - #[test] - fn convert_i8() { - assert_eq!( - TypeId::of::<::__Inner>(), - TypeId::of::() - ); - assert_eq!(::__from_declared_param(-3), -3); - assert_eq!(EncodeConvertArgument::__into_argument(-3i32).0, -3); - } - - #[test] - fn convert_bool() { - assert!(!::__from_declared_param( - Bool::NO - )); - assert!(::__from_declared_param( - Bool::YES - )); - assert!(!::__from_return(Bool::NO)); - assert!(::__from_return(Bool::YES)); - - assert!(!EncodeConvertArgument::__into_argument(false).0.as_bool()); - assert!(EncodeConvertArgument::__into_argument(true).0.as_bool()); - assert!(!EncodeConvertReturn::__into_declared_return(false).as_bool()); - assert!(EncodeConvertReturn::__into_declared_return(true).as_bool()); - - #[cfg(all(feature = "apple", target_os = "macos", target_arch = "x86_64"))] - assert_eq!( - ::__Inner::ENCODING, - Encoding::Char - ); - } - - #[test] - fn test_encode_arguments() { - assert!(<()>::ENCODINGS.is_empty()); - assert_eq!(<(i8,)>::ENCODINGS, &[i8::ENCODING]); - assert_eq!(<(i8, u32)>::ENCODINGS, &[i8::ENCODING, u32::ENCODING]); - } -} diff --git a/crates/objc2/src/macros/declare_class.rs b/crates/objc2/src/macros/declare_class.rs index db70e08b7..9a05c3154 100644 --- a/crates/objc2/src/macros/declare_class.rs +++ b/crates/objc2/src/macros/declare_class.rs @@ -922,7 +922,7 @@ macro_rules! __declare_class_rewrite_args { } => { $crate::__declare_class_rewrite_args! { ($($($rest_args)*)?) - ($($args_converted)* _ : <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__Inner,) + ($($args_converted)* _ : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,) ($($body_prefix)*) ($out_macro) @@ -940,10 +940,10 @@ macro_rules! __declare_class_rewrite_args { } => { $crate::__declare_class_rewrite_args! { ($($($rest_args)*)?) - ($($args_converted)* $param : <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__Inner,) + ($($args_converted)* $param : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,) ( $($body_prefix)* - let mut $param = <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__from_declared_param($param); + let mut $param = <$param_ty as $crate::__macro_helpers::ConvertArgument>::__from_declared_param($param); ) ($out_macro) @@ -961,10 +961,10 @@ macro_rules! __declare_class_rewrite_args { } => { $crate::__declare_class_rewrite_args! { ($($($rest_args)*)?) - ($($args_converted)* $param : <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__Inner,) + ($($args_converted)* $param : <$param_ty as $crate::__macro_helpers::ConvertArgument>::__Inner,) ( $($body_prefix)* - let $param = <$param_ty as $crate::encode::__unstable::EncodeConvertArgument>::__from_declared_param($param); + let $param = <$param_ty as $crate::__macro_helpers::ConvertArgument>::__from_declared_param($param); ) ($out_macro) @@ -1015,7 +1015,7 @@ macro_rules! __declare_class_method_out_inner { $($qualifiers)* extern "C" fn $name( $($args_prefix)* $($args_converted)* - ) $(-> <$ret as $crate::encode::__unstable::EncodeConvertReturn>::__Inner)? { + ) $(-> <$ret as $crate::__macro_helpers::ConvertReturn>::__Inner)? { $($body_prefix)* $crate::__convert_result! { $body $(; $ret)? @@ -1100,9 +1100,7 @@ macro_rules! __convert_result { ($body:block; $ret:ty) => { let __objc2_result = $body; #[allow(unreachable_code)] - <$ret as $crate::encode::__unstable::EncodeConvertReturn>::__into_declared_return( - __objc2_result, - ) + <$ret as $crate::__macro_helpers::ConvertReturn>::__into_declared_return(__objc2_result) }; } diff --git a/crates/objc2/src/message/apple/arm.rs b/crates/objc2/src/message/apple/arm.rs index 4c4aa4e4a..8c49dd206 100644 --- a/crates/objc2/src/message/apple/arm.rs +++ b/crates/objc2/src/message/apple/arm.rs @@ -1,8 +1,7 @@ use core::mem; use super::MsgSendFn; -use crate::encode::Encoding; -use crate::encode::__unstable::EncodeReturn; +use crate::encode::{EncodeReturn, Encoding}; use crate::ffi; use crate::runtime::Imp; diff --git a/crates/objc2/src/message/apple/arm64.rs b/crates/objc2/src/message/apple/arm64.rs index 9366d631d..f309c51d4 100644 --- a/crates/objc2/src/message/apple/arm64.rs +++ b/crates/objc2/src/message/apple/arm64.rs @@ -1,5 +1,5 @@ use super::MsgSendFn; -use crate::encode::__unstable::EncodeReturn; +use crate::encode::EncodeReturn; use crate::ffi; use crate::runtime::Imp; diff --git a/crates/objc2/src/message/apple/mod.rs b/crates/objc2/src/message/apple/mod.rs index f14b8db80..a98d0e3e9 100644 --- a/crates/objc2/src/message/apple/mod.rs +++ b/crates/objc2/src/message/apple/mod.rs @@ -1,4 +1,4 @@ -use crate::encode::__unstable::EncodeReturn; +use crate::encode::EncodeReturn; use crate::ffi; use crate::runtime::{AnyClass, AnyObject, Imp, Sel}; use crate::MessageArguments; diff --git a/crates/objc2/src/message/apple/x86.rs b/crates/objc2/src/message/apple/x86.rs index ef5497413..98ab29d94 100644 --- a/crates/objc2/src/message/apple/x86.rs +++ b/crates/objc2/src/message/apple/x86.rs @@ -1,8 +1,7 @@ use core::mem; use super::MsgSendFn; -use crate::encode::Encoding; -use crate::encode::__unstable::EncodeReturn; +use crate::encode::{EncodeReturn, Encoding}; use crate::ffi; use crate::runtime::Imp; diff --git a/crates/objc2/src/message/apple/x86_64.rs b/crates/objc2/src/message/apple/x86_64.rs index 5d4fb0d02..1cfba2bd9 100644 --- a/crates/objc2/src/message/apple/x86_64.rs +++ b/crates/objc2/src/message/apple/x86_64.rs @@ -1,8 +1,7 @@ use core::mem; use super::MsgSendFn; -use crate::encode::Encoding; -use crate::encode::__unstable::EncodeReturn; +use crate::encode::{EncodeReturn, Encoding}; use crate::ffi; use crate::runtime::Imp; diff --git a/crates/objc2/src/message/gnustep.rs b/crates/objc2/src/message/gnustep.rs index 5f9510d42..4a2c02795 100644 --- a/crates/objc2/src/message/gnustep.rs +++ b/crates/objc2/src/message/gnustep.rs @@ -1,7 +1,7 @@ use core::hint; use core::mem; -use crate::encode::__unstable::EncodeReturn; +use crate::encode::EncodeReturn; use crate::ffi; use crate::runtime::{AnyClass, AnyObject, Imp, Sel}; use crate::MessageArguments; diff --git a/crates/objc2/src/message/mod.rs b/crates/objc2/src/message/mod.rs index 1cc4ce48f..4e797c330 100644 --- a/crates/objc2/src/message/mod.rs +++ b/crates/objc2/src/message/mod.rs @@ -2,10 +2,8 @@ use core::mem; use core::mem::ManuallyDrop; use core::ptr::{self, NonNull}; -use crate::encode::__unstable::{ - EncodeArguments, EncodeConvertArgument, EncodeConvertReturn, EncodeReturn, -}; -use crate::encode::{Encode, RefEncode}; +use crate::__macro_helpers::{ConvertArgument, ConvertReturn}; +use crate::encode::{Encode, EncodeArgument, EncodeReturn, Encoding, RefEncode}; use crate::mutability::IsMutable; use crate::rc::Id; use crate::runtime::{AnyClass, AnyObject, Imp, Sel}; @@ -50,14 +48,25 @@ fn msg_send_check( args: &[crate::encode::Encoding], ret: &crate::encode::Encoding, ) { - use crate::verify::{verify_method_signature, Inner, VerificationError}; - let cls = if let Some(obj) = obj { obj.class() } else { panic_null(sel) }; + msg_send_check_class(cls, sel, args, ret); +} + +#[cfg(debug_assertions)] +#[track_caller] +fn msg_send_check_class( + cls: &AnyClass, + sel: Sel, + args: &[crate::encode::Encoding], + ret: &crate::encode::Encoding, +) { + use crate::verify::{verify_method_signature, Inner, VerificationError}; + let err = if let Some(method) = cls.instance_method(sel) { if let Err(err) = verify_method_signature(method, args, ret) { err @@ -221,16 +230,16 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { unsafe fn send_message(self, sel: Sel, args: A) -> R where A: MessageArguments, - R: EncodeConvertReturn, + R: ConvertReturn, { let this = self.__as_raw_receiver(); #[cfg(debug_assertions)] { // SAFETY: Caller ensures only valid or NULL pointers. let obj = unsafe { this.as_ref() }; - msg_send_check(obj, sel, A::ENCODINGS, &R::__Inner::ENCODING_RETURN); + msg_send_check(obj, sel, A::__ENCODINGS, &R::__Inner::ENCODING_RETURN); } - unsafe { EncodeConvertReturn::__from_return(send_unverified(this, sel, args)) } + unsafe { ConvertReturn::__from_return(send_unverified(this, sel, args)) } } /// Sends a message to a specific superclass with the given selector and @@ -260,7 +269,7 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { unsafe fn send_super_message(self, superclass: &AnyClass, sel: Sel, args: A) -> R where A: MessageArguments, - R: EncodeConvertReturn, + R: ConvertReturn, { let this = self.__as_raw_receiver(); #[cfg(debug_assertions)] @@ -268,13 +277,14 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { if this.is_null() { panic_null(sel); } - if let Err(err) = superclass.verify_sel::(sel) { - panic_verify(superclass, sel, &err); - } - } - unsafe { - EncodeConvertReturn::__from_return(send_super_unverified(this, superclass, sel, args)) + msg_send_check_class( + superclass, + sel, + A::__ENCODINGS, + &R::__Inner::ENCODING_RETURN, + ); } + unsafe { ConvertReturn::__from_return(send_super_unverified(this, superclass, sel, args)) } } #[inline] @@ -285,7 +295,7 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { Self::__Inner: ClassType, ::Super: ClassType, A: MessageArguments, - R: EncodeConvertReturn, + R: ConvertReturn, { unsafe { self.send_super_message(::Super::class(), sel, args) } } @@ -479,6 +489,10 @@ unsafe impl<'a> MessageReceiver for &'a AnyClass { } } +mod message_args_private { + pub trait Sealed {} +} + /// Types that may be used as the arguments of an Objective-C message. /// /// This is implemented for tuples of up to 16 arguments, where each argument @@ -489,7 +503,10 @@ unsafe impl<'a> MessageReceiver for &'a AnyClass { /// /// This is a sealed trait, and should not need to be implemented. Open an /// issue if you know a use-case where this restrition should be lifted! -pub unsafe trait MessageArguments: EncodeArguments { +pub unsafe trait MessageArguments: message_args_private::Sealed { + #[doc(hidden)] + const __ENCODINGS: &'static [Encoding]; + /// Invoke an [`Imp`] with the given object, selector, and arguments. /// /// This method is the primitive used when sending messages and should not @@ -508,10 +525,16 @@ pub trait __TupleExtender { macro_rules! message_args_impl { ($($a:ident: $t:ident),*) => ( - unsafe impl<$($t: EncodeConvertArgument),*> MessageArguments for ($($t,)*) { + impl<$($t: ConvertArgument),*> message_args_private::Sealed for ($($t,)*) {} + + unsafe impl<$($t: ConvertArgument),*> MessageArguments for ($($t,)*) { + const __ENCODINGS: &'static [Encoding] = &[ + $($t::__Inner::ENCODING_ARGUMENT),* + ]; + #[inline] unsafe fn __invoke(imp: Imp, obj: *mut AnyObject, sel: Sel, ($($a,)*): Self) -> R { - $(let $a = EncodeConvertArgument::__into_argument($a);)* + $(let $a = ConvertArgument::__into_argument($a);)* // The imp must be cast to the appropriate function pointer // type before being called; the msgSend functions are not @@ -536,8 +559,9 @@ macro_rules! message_args_impl { $( // SAFETY: The argument was passed to the message sending // function, and the stored values are only processed this - // once. See `src/rc/writeback.rs` for details. - unsafe { <$t as EncodeConvertArgument>::__process_after_message_send($a.1) }; + // once. See `src/__macro_helpers/writeback.rs` for + // details. + unsafe { <$t as ConvertArgument>::__process_after_message_send($a.1) }; )* result } diff --git a/crates/objc2/src/rc/mod.rs b/crates/objc2/src/rc/mod.rs index 934c9a21a..4c6dc0953 100644 --- a/crates/objc2/src/rc/mod.rs +++ b/crates/objc2/src/rc/mod.rs @@ -55,7 +55,6 @@ mod id_forwarding_impls; mod id_traits; mod test_object; mod weak_id; -mod writeback; pub use self::allocated::Allocated; pub use self::autorelease::{ diff --git a/crates/objc2/src/runtime/bool.rs b/crates/objc2/src/runtime/bool.rs index c649168ea..74b4bf9c0 100644 --- a/crates/objc2/src/runtime/bool.rs +++ b/crates/objc2/src/runtime/bool.rs @@ -137,7 +137,7 @@ unsafe impl RefEncode for Bool { #[cfg(test)] mod tests { use super::*; - use crate::encode::__unstable::{EncodeConvertArgument, EncodeConvertReturn}; + use crate::__macro_helpers::{ConvertArgument, ConvertReturn}; use alloc::format; #[test] @@ -175,12 +175,12 @@ mod tests { assert_eq!(bool::__ENCODING, Encoding::Bool); assert_eq!( - ::__Inner::__ENCODING, - ::__Inner::ENCODING + ::__Inner::__ENCODING, + ::__Inner::ENCODING ); assert_eq!( - ::__Inner::__ENCODING, - ::__Inner::ENCODING + ::__Inner::__ENCODING, + ::__Inner::ENCODING ); } diff --git a/crates/objc2/src/runtime/mod.rs b/crates/objc2/src/runtime/mod.rs index 416e0c04c..5e6a75d9a 100644 --- a/crates/objc2/src/runtime/mod.rs +++ b/crates/objc2/src/runtime/mod.rs @@ -42,8 +42,7 @@ mod retain_release_fast; pub(crate) use self::method_encoding_iter::{EncodingParseError, MethodEncodingIter}; pub(crate) use self::retain_release_fast::{objc_release_fast, objc_retain_fast}; -use crate::encode::__unstable::{EncodeArguments, EncodeConvertReturn, EncodeReturn}; -use crate::encode::{Encode, Encoding, OptionEncode, RefEncode}; +use crate::encode::{Encode, EncodeArguments, EncodeReturn, Encoding, OptionEncode, RefEncode}; use crate::verify::{verify_method_signature, Inner}; use crate::{ffi, Message}; @@ -816,25 +815,25 @@ impl AnyClass { /// # Example /// /// ``` - /// # use objc2::{class, sel}; - /// # use objc2::runtime::AnyClass; + /// use objc2::{class, sel}; + /// use objc2::runtime::{AnyClass, Bool}; /// let cls = class!(NSObject); /// let sel = sel!(isKindOfClass:); /// // Verify that `isKindOfClass:`: /// // - Exists on the class /// // - Takes a class as a parameter /// // - Returns a BOOL - /// let result = cls.verify_sel::<(&AnyClass,), bool>(sel); + /// let result = cls.verify_sel::<(&AnyClass,), Bool>(sel); /// assert!(result.is_ok()); /// ``` #[allow(clippy::missing_errors_doc)] // Written differently in the docs pub fn verify_sel(&self, sel: Sel) -> Result<(), VerificationError> where A: EncodeArguments, - R: EncodeConvertReturn, + R: EncodeReturn, { let method = self.instance_method(sel).ok_or(Inner::MethodNotFound)?; - verify_method_signature(method, A::ENCODINGS, &R::__Inner::ENCODING_RETURN) + verify_method_signature(method, A::ENCODINGS, &R::ENCODING_RETURN) } } diff --git a/crates/test-ui/ui/add_method_no_bool.stderr b/crates/test-ui/ui/add_method_no_bool.stderr index 5afc8ae5f..ab1ac8a6a 100644 --- a/crates/test-ui/ui/add_method_no_bool.stderr +++ b/crates/test-ui/ui/add_method_no_bool.stderr @@ -16,6 +16,7 @@ error[E0277]: the trait bound `bool: Encode` is not satisfied u8 u16 and $N others + = note: required for `bool` to implement `EncodeArgument` = note: required for `unsafe extern "C" fn(&NSObject, objc2::runtime::Sel, bool)` to implement `MethodImplementation` note: required by a bound in `ClassBuilder::add_method` --> $WORKSPACE/crates/objc2/src/declare/mod.rs diff --git a/crates/test-ui/ui/declare_class_invalid_type.stderr b/crates/test-ui/ui/declare_class_invalid_type.stderr index 91f497a9d..76136f8b6 100644 --- a/crates/test-ui/ui/declare_class_invalid_type.stderr +++ b/crates/test-ui/ui/declare_class_invalid_type.stderr @@ -21,13 +21,13 @@ error[E0277]: the trait bound `Id: Encode` is not satisfied u16 and $N others = note: required for `Id` to implement `EncodeReturn` - = note: required for `Id` to implement `__unstable::convert_private::Sealed` -note: required by a bound in `EncodeConvertReturn` - --> $WORKSPACE/crates/objc2/src/encode/__unstable.rs + = note: required for `Id` to implement `__macro_helpers::convert::return_private::Sealed` +note: required by a bound in `ConvertReturn` + --> $WORKSPACE/crates/objc2/src/__macro_helpers/convert.rs | - | pub trait EncodeConvertReturn: convert_private::Sealed { - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EncodeConvertReturn` - = note: `EncodeConvertReturn` is a "sealed trait", because to implement it you also need to implement `objc2::encode::__unstable::convert_private::Sealed`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it + | pub trait ConvertReturn: return_private::Sealed { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ConvertReturn` + = note: `ConvertReturn` is a "sealed trait", because to implement it you also need to implement `objc2::__macro_helpers::convert::return_private::Sealed`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it = note: this error originates in the macro `$crate::__declare_class_method_out_inner` which comes from the expansion of the macro `declare_class` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Vec<()>: Encode` is not satisfied @@ -53,13 +53,13 @@ error[E0277]: the trait bound `Vec<()>: Encode` is not satisfied u16 and $N others = note: required for `Vec<()>` to implement `EncodeReturn` - = note: required for `Vec<()>` to implement `__unstable::convert_private::Sealed` -note: required by a bound in `EncodeConvertReturn` - --> $WORKSPACE/crates/objc2/src/encode/__unstable.rs + = note: required for `Vec<()>` to implement `__macro_helpers::convert::return_private::Sealed` +note: required by a bound in `ConvertReturn` + --> $WORKSPACE/crates/objc2/src/__macro_helpers/convert.rs | - | pub trait EncodeConvertReturn: convert_private::Sealed { - | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EncodeConvertReturn` - = note: `EncodeConvertReturn` is a "sealed trait", because to implement it you also need to implement `objc2::encode::__unstable::convert_private::Sealed`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it + | pub trait ConvertReturn: return_private::Sealed { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ConvertReturn` + = note: `ConvertReturn` is a "sealed trait", because to implement it you also need to implement `objc2::__macro_helpers::convert::return_private::Sealed`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it = note: this error originates in the macro `$crate::__declare_class_method_out_inner` which comes from the expansion of the macro `declare_class` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Box: Encode` is not satisfied @@ -84,7 +84,14 @@ error[E0277]: the trait bound `Box: Encode` is not satisfied u8 u16 and $N others - = note: required for `Box` to implement `EncodeConvertArgument` + = note: required for `Box` to implement `EncodeArgument` + = note: required for `Box` to implement `__macro_helpers::convert::argument_private::Sealed` +note: required by a bound in `ConvertArgument` + --> $WORKSPACE/crates/objc2/src/__macro_helpers/convert.rs + | + | pub trait ConvertArgument: argument_private::Sealed { + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ConvertArgument` + = note: `ConvertArgument` is a "sealed trait", because to implement it you also need to implement `objc2::__macro_helpers::convert::argument_private::Sealed`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it = note: this error originates in the macro `$crate::__declare_class_rewrite_args` which comes from the expansion of the macro `declare_class` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `CustomObject: Encode` is not satisfied @@ -109,5 +116,12 @@ error[E0277]: the trait bound `CustomObject: Encode` is not satisfied u8 u16 and $N others - = note: required for `CustomObject` to implement `EncodeConvertArgument` + = note: required for `CustomObject` to implement `EncodeArgument` + = note: required for `CustomObject` to implement `__macro_helpers::convert::argument_private::Sealed` +note: required by a bound in `ConvertArgument` + --> $WORKSPACE/crates/objc2/src/__macro_helpers/convert.rs + | + | pub trait ConvertArgument: argument_private::Sealed { + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `ConvertArgument` + = note: `ConvertArgument` is a "sealed trait", because to implement it you also need to implement `objc2::__macro_helpers::convert::argument_private::Sealed`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it = note: this error originates in the macro `$crate::__declare_class_rewrite_args` which comes from the expansion of the macro `declare_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/extern_methods_invalid_type.stderr b/crates/test-ui/ui/extern_methods_invalid_type.stderr index 51cbe890a..a3cbca96d 100644 --- a/crates/test-ui/ui/extern_methods_invalid_type.stderr +++ b/crates/test-ui/ui/extern_methods_invalid_type.stderr @@ -20,15 +20,15 @@ error[E0277]: the trait bound `Id: Encode` is not satisfied u16 and $N others = note: required for `Id` to implement `EncodeReturn` - = note: required for `Id` to implement `EncodeConvertReturn` + = note: required for `Id` to implement `ConvertReturn` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs | | unsafe fn send_message(self, sel: Sel, args: A) -> R | ------------ required by a bound in this associated function ... - | R: EncodeConvertReturn, - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` + | R: ConvertReturn, + | ^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` = note: this error originates in the macro `$crate::__msg_send_helper` which comes from the expansion of the macro `extern_methods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `i32: MaybeUnwrap` is not satisfied @@ -99,15 +99,15 @@ error[E0277]: the trait bound `Result<(), Id>: Encode` is not satisfie u16 and $N others = note: required for `Result<(), Id>` to implement `EncodeReturn` - = note: required for `Result<(), Id>` to implement `EncodeConvertReturn` + = note: required for `Result<(), Id>` to implement `ConvertReturn` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs | | unsafe fn send_message(self, sel: Sel, args: A) -> R | ------------ required by a bound in this associated function ... - | R: EncodeConvertReturn, - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` + | R: ConvertReturn, + | ^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` = note: this error originates in the macro `$crate::__msg_send_helper` which comes from the expansion of the macro `extern_methods` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Result, Id>: MaybeUnwrap` is not satisfied @@ -155,13 +155,13 @@ error[E0277]: the trait bound `MainThreadMarker: Encode` is not satisfied u16 and $N others = note: required for `MainThreadMarker` to implement `EncodeReturn` - = note: required for `MainThreadMarker` to implement `EncodeConvertReturn` + = note: required for `MainThreadMarker` to implement `ConvertReturn` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs | | unsafe fn send_message(self, sel: Sel, args: A) -> R | ------------ required by a bound in this associated function ... - | R: EncodeConvertReturn, - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` + | R: ConvertReturn, + | ^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` = note: this error originates in the macro `$crate::__msg_send_helper` which comes from the expansion of the macro `extern_methods` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/global_block_not_encode.stderr b/crates/test-ui/ui/global_block_not_encode.stderr index 3f9c39013..4e7cd95e1 100644 --- a/crates/test-ui/ui/global_block_not_encode.stderr +++ b/crates/test-ui/ui/global_block_not_encode.stderr @@ -16,6 +16,7 @@ error[E0277]: the trait bound `Box: objc2::encode::Encode` is not satisfied u8 u16 and $N others + = note: required for `Box` to implement `objc2::encode::EncodeArgument` = note: required for `(Box,)` to implement `BlockArguments` = note: required for `GlobalBlock<(Box,)>` to implement `Sync` = note: shared static variables must have a type that implements `Sync` diff --git a/crates/test-ui/ui/invalid_option_encode_impl.stderr b/crates/test-ui/ui/invalid_option_encode_impl.stderr index 9edbd7d11..52117ea5e 100644 --- a/crates/test-ui/ui/invalid_option_encode_impl.stderr +++ b/crates/test-ui/ui/invalid_option_encode_impl.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of ` as objc2::Encode>::ENCODING` failed - --> $WORKSPACE/crates/objc2/src/encode/mod.rs + --> $WORKSPACE/crates/objc2/src/encode.rs | | panic!("invalid OptionEncode + Encode implementation"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'invalid OptionEncode + Encode implementation', $WORKSPACE/crates/objc2/src/encode/mod.rs:276:13 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'invalid OptionEncode + Encode implementation', $WORKSPACE/crates/objc2/src/encode.rs:273:13 | = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/invalid_option_encode_impl_ref.stderr b/crates/test-ui/ui/invalid_option_encode_impl_ref.stderr index 4b44c1dca..d1a441dd5 100644 --- a/crates/test-ui/ui/invalid_option_encode_impl_ref.stderr +++ b/crates/test-ui/ui/invalid_option_encode_impl_ref.stderr @@ -1,8 +1,8 @@ error[E0080]: evaluation of ` as objc2::RefEncode>::ENCODING_REF` failed - --> $WORKSPACE/crates/objc2/src/encode/mod.rs + --> $WORKSPACE/crates/objc2/src/encode.rs | | panic!("invalid OptionEncode + RefEncode implementation"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'invalid OptionEncode + RefEncode implementation', $WORKSPACE/crates/objc2/src/encode/mod.rs:286:13 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'invalid OptionEncode + RefEncode implementation', $WORKSPACE/crates/objc2/src/encode.rs:283:13 | = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/msg_send_not_encode.stderr b/crates/test-ui/ui/msg_send_not_encode.stderr index 1921994c1..9e163630e 100644 --- a/crates/test-ui/ui/msg_send_not_encode.stderr +++ b/crates/test-ui/ui/msg_send_not_encode.stderr @@ -15,15 +15,15 @@ error[E0277]: the trait bound `Vec: Encode` is not satisfied u16 and $N others = note: required for `Vec` to implement `EncodeReturn` - = note: required for `Vec` to implement `EncodeConvertReturn` + = note: required for `Vec` to implement `ConvertReturn` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs | | unsafe fn send_message(self, sel: Sel, args: A) -> R | ------------ required by a bound in this associated function ... - | R: EncodeConvertReturn, - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` + | R: ConvertReturn, + | ^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` = note: this error originates in the macro `$crate::__msg_send_helper` which comes from the expansion of the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Vec: Encode` is not satisfied @@ -45,7 +45,8 @@ error[E0277]: the trait bound `Vec: Encode` is not satisfied u8 u16 and $N others - = note: required for `Vec` to implement `EncodeConvertArgument` + = note: required for `Vec` to implement `EncodeArgument` + = note: required for `Vec` to implement `ConvertArgument` = note: required for `(Vec,)` to implement `MessageArguments` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs @@ -76,7 +77,8 @@ error[E0277]: the trait bound `(): Encode` is not satisfied u8 u16 and $N others - = note: required for `()` to implement `EncodeConvertArgument` + = note: required for `()` to implement `EncodeArgument` + = note: required for `()` to implement `ConvertArgument` = note: required for `((),)` to implement `MessageArguments` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs diff --git a/crates/test-ui/ui/not_encode.stderr b/crates/test-ui/ui/not_encode.stderr index 32996fa3a..cd9202f3a 100644 --- a/crates/test-ui/ui/not_encode.stderr +++ b/crates/test-ui/ui/not_encode.stderr @@ -135,6 +135,7 @@ error[E0277]: the trait bound `(): Encode` is not satisfied u8 u16 and $N others + = note: required for `()` to implement `EncodeArgument` = note: required for `((), i32)` to implement `BlockArguments` = note: required for `block2::Block<((), i32), ()>` to implement `RefEncode` = note: required for `&block2::Block<((), i32), ()>` to implement `Encode` diff --git a/crates/test-ui/ui/not_writeback.stderr b/crates/test-ui/ui/not_writeback.stderr index 11ddc1cbd..a74d90326 100644 --- a/crates/test-ui/ui/not_writeback.stderr +++ b/crates/test-ui/ui/not_writeback.stderr @@ -16,15 +16,15 @@ error[E0277]: the trait bound `Id: RefEncode` is not satisfied and $N others = note: required for `&mut Id` to implement `Encode` = note: required for `&mut Id` to implement `EncodeReturn` - = note: required for `&mut Id` to implement `EncodeConvertReturn` + = note: required for `&mut Id` to implement `ConvertReturn` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs | | unsafe fn send_message(self, sel: Sel, args: A) -> R | ------------ required by a bound in this associated function ... - | R: EncodeConvertReturn, - | ^^^^^^^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` + | R: ConvertReturn, + | ^^^^^^^^^^^^^ required by this bound in `MessageReceiver::send_message` = note: this error originates in the macro `$crate::__msg_send_helper` which comes from the expansion of the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the trait bound `Id: Encode` is not satisfied @@ -46,7 +46,8 @@ error[E0277]: the trait bound `Id: Encode` is not satisfied u8 u16 and $N others - = note: required for `Id` to implement `EncodeConvertArgument` + = note: required for `Id` to implement `EncodeArgument` + = note: required for `Id` to implement `ConvertArgument` = note: required for `(Id,)` to implement `MessageArguments` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs @@ -78,7 +79,8 @@ error[E0277]: the trait bound `Id: RefEncode` is not satisfied u16 and $N others = note: required for `&Id` to implement `Encode` - = note: required for `&Id` to implement `EncodeConvertArgument` + = note: required for `&Id` to implement `EncodeArgument` + = note: required for `&Id` to implement `ConvertArgument` = note: required for `(&Id,)` to implement `MessageArguments` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs @@ -112,7 +114,8 @@ error[E0277]: the trait bound `Id: RefEncode` is not satisfied = note: required for `&Id` to implement `Encode` = note: 1 redundant requirement hidden = note: required for `Option<&Id>` to implement `Encode` - = note: required for `Option<&Id>` to implement `EncodeConvertArgument` + = note: required for `Option<&Id>` to implement `EncodeArgument` + = note: required for `Option<&Id>` to implement `ConvertArgument` = note: required for `(Option<&Id>,)` to implement `MessageArguments` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs @@ -144,7 +147,8 @@ error[E0277]: the trait bound `Id: RefEncode` is not satisfied u16 and $N others = note: required for `*mut Id` to implement `Encode` - = note: required for `*mut Id` to implement `EncodeConvertArgument` + = note: required for `*mut Id` to implement `EncodeArgument` + = note: required for `*mut Id` to implement `ConvertArgument` = note: required for `(*mut Id,)` to implement `MessageArguments` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs @@ -177,7 +181,8 @@ error[E0277]: the trait bound `Id: RefEncode` is not satisfied and $N others = note: required for `&mut Id` to implement `RefEncode` = note: required for `&mut &mut Id` to implement `Encode` - = note: required for `&mut &mut Id` to implement `EncodeConvertArgument` + = note: required for `&mut &mut Id` to implement `EncodeArgument` + = note: required for `&mut &mut Id` to implement `ConvertArgument` = note: required for `(&mut &mut Id,)` to implement `MessageArguments` note: required by a bound in `send_message` --> $WORKSPACE/crates/objc2/src/message/mod.rs