From 1033a13c939422b2484c9227fa9dfa820c8da787 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 4 Mar 2026 18:19:49 +0100 Subject: [PATCH 1/2] Expose static encoding string support in objc2-encode Add `Encoding::str_len` and `Encoding::str_array`. Will probably be needed in this form, regardless of whether `generic_const_exprs` ever lands. --- crates/objc2-encode/CHANGELOG.md | 2 + crates/objc2-encode/src/encoding.rs | 79 +++++++++++++- crates/objc2-encode/src/lib.rs | 3 - crates/objc2-encode/src/static_str.rs | 121 ++++++++++++++-------- crates/objc2/tests/generic_const_exprs.rs | 37 +++++++ crates/tests/src/test_encode_utils.rs | 8 +- 6 files changed, 198 insertions(+), 52 deletions(-) create mode 100644 crates/objc2/tests/generic_const_exprs.rs diff --git a/crates/objc2-encode/CHANGELOG.md b/crates/objc2-encode/CHANGELOG.md index a43476748..c6975f976 100644 --- a/crates/objc2-encode/CHANGELOG.md +++ b/crates/objc2-encode/CHANGELOG.md @@ -8,6 +8,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added * Added `Encoding::Int128` and `Encoding::UInt128`. +* Added `Encoding::str_len` and `Encoding::str_array` to allow statically + constructing encoding strings. ### Changed * Equivalence comparisons now consider `Encoding::String` as equivalent to diff --git a/crates/objc2-encode/src/encoding.rs b/crates/objc2-encode/src/encoding.rs index e2dffcbb4..6ce0048c4 100644 --- a/crates/objc2-encode/src/encoding.rs +++ b/crates/objc2-encode/src/encoding.rs @@ -2,6 +2,7 @@ use core::fmt; use crate::helper::{compare_encodings, Helper, NestingLevel}; use crate::parse::Parser; +use crate::static_str::{static_encoding_str_array, static_encoding_str_len}; use crate::EncodingBox; /// An Objective-C type-encoding. @@ -281,6 +282,81 @@ impl Encoding { pub fn size(&self) -> Option { Helper::new(self).size(NestingLevel::new()) } + + /// The length of the encoding when turned into a string. + /// + /// This returns the same value as `self.to_string().len()`, but is + /// available in `const` to allow constructing static encoding strings. + /// + /// See [`str_array`][Self::str_array] for more information. + pub const fn str_len(&self) -> usize { + static_encoding_str_len(self, NestingLevel::new()) + } + + /// An array containing the encoding's contents. + /// + /// The length should be at least [`str_len`][Self::str_len], remaining + /// bytes are zero-filled. + /// + /// This is equivalent to `self.to_string().to_bytes()`, but is available + /// in `const` to allow constructing static encoding strings. + /// + /// This is most often useful in macros - it is not really possible to use + /// in generics yet, it requires [`#![feature(generic_const_exprs)]`][g], + /// but once that's available, this should be useful there too. + /// + /// [g]: https://github.com/rust-lang/rust/issues/76560 + /// + /// # Panics + /// + /// Panics if `LEN` is less than [`str_len`][Self::str_len], or if the + /// encoding contains structs or unions with invalid identifiers. + /// + /// # Example + /// + /// Construct an encoding string at `const`-time. + /// + /// ``` + /// use core::ffi::CStr; + /// use objc2_encode::Encoding; + /// + /// // Let's say you have some constant encoding. + /// const ENCODING: Encoding = Encoding::Pointer(&Encoding::Struct("foo", &[Encoding::Sel, Encoding::Int])); + /// + /// // This can be converted to a constant string. + /// // + /// // SAFETY: `.str_array()` is guaranteed to be valid UTF-8. + /// const ENCODING_STR: &str = unsafe { + /// str::from_utf8_unchecked(&ENCODING.str_array::<{ ENCODING.str_len() }>()) + /// }; + /// assert_eq!(ENCODING_STR, "^{foo=:i}"); + /// + /// // Or to a constant C-string. + /// // + /// // SAFETY: `.str_array()` is guaranteed to not contain any NUL bytes, + /// // apart from at the end because we specify `.str_len() + 1`. + /// const ENCODING_CSTR: &CStr = unsafe { + /// CStr::from_bytes_with_nul_unchecked(&ENCODING.str_array::<{ ENCODING.str_len() + 1 }>()) + /// }; + /// assert_eq!(ENCODING_CSTR, c"^{foo=:i}"); + /// ``` + /// + /// Attempt to construct an encoding string from an invalid encoding. + /// + /// ```should_panic + /// use objc2_encode::Encoding; + /// + /// // Invalid struct name (`-` is not an identifier). + /// const ENCODING: Encoding = Encoding::Pointer(&Encoding::Struct("-", &[Encoding::Int])); + /// + /// // This will panic. + /// let _ = str::from_utf8(&ENCODING.str_array::<{ ENCODING.str_len() }>()).unwrap(); + /// + /// // If we did ^ at `const`-time, it would be a post-mono compile-error. + /// ``` + pub const fn str_array(&self) -> [u8; LEN] { + static_encoding_str_array(self, NestingLevel::new()) + } } /// Formats this [`Encoding`] in a similar way that the `@encode` directive @@ -298,7 +374,6 @@ impl fmt::Display for Encoding { #[cfg(test)] mod tests { use super::*; - use crate::static_str::{static_encoding_str_array, static_encoding_str_len}; use alloc::boxed::Box; use alloc::string::ToString; use alloc::vec; @@ -387,7 +462,7 @@ mod tests { )* // Check static str - const STATIC_ENCODING_DATA: [u8; static_encoding_str_len(&E, NestingLevel::new())] = static_encoding_str_array(&E, NestingLevel::new()); + const STATIC_ENCODING_DATA: [u8; E.str_len()] = E.str_array(); const STATIC_ENCODING_STR: &str = unsafe { core::str::from_utf8_unchecked(&STATIC_ENCODING_DATA) }; assert_eq!(STATIC_ENCODING_STR, $string, "static"); } diff --git a/crates/objc2-encode/src/lib.rs b/crates/objc2-encode/src/lib.rs index a7051e4e7..1bebfaa61 100644 --- a/crates/objc2-encode/src/lib.rs +++ b/crates/objc2-encode/src/lib.rs @@ -54,9 +54,6 @@ mod encoding; mod encoding_box; mod helper; mod parse; - -// Will be used outside tests at some point when generic constants are available -#[cfg(test)] mod static_str; pub use self::encoding::Encoding; diff --git a/crates/objc2-encode/src/static_str.rs b/crates/objc2-encode/src/static_str.rs index a04e5fd10..2d45b7ad8 100644 --- a/crates/objc2-encode/src/static_str.rs +++ b/crates/objc2-encode/src/static_str.rs @@ -1,3 +1,5 @@ +//! Convert encodings to strings at `const`-time. + use crate::{ helper::{ContainerKind, Helper, NestingLevel}, parse::verify_name, @@ -5,7 +7,10 @@ use crate::{ use super::Encoding; -pub(crate) const fn static_int_str_len(mut n: u64) -> usize { +/// Length of the integer when formatted in base 10. +/// +/// This will never return more than `20`. +const fn static_int_str_len(mut n: u64) -> usize { let mut i = 0; if n == 0 { return 1; @@ -17,7 +22,8 @@ pub(crate) const fn static_int_str_len(mut n: u64) -> usize { i } -pub(crate) const fn static_int_str_array(mut n: u64) -> [u8; RES] { +/// Integer formatted in base 10 and placed in an array. +const fn static_int_str_array(mut n: u64) -> [u8; RES] { let mut res: [u8; RES] = [0; RES]; let mut i = 0; if n == 0 { @@ -40,23 +46,23 @@ pub(crate) const fn static_int_str_array(mut n: u64) -> [u8; R rev } +/// Length of the encoding string. pub(crate) const fn static_encoding_str_len(encoding: &Encoding, level: NestingLevel) -> usize { - use Helper::*; - match Helper::new(encoding) { - Primitive(primitive) => primitive.to_str().len(), - BitField(size, None) => 1 + static_int_str_len(size as u64), - BitField(size, Some((offset, t))) => { + Helper::Primitive(primitive) => primitive.to_str().len(), + Helper::BitField(size, None) => 1 + static_int_str_len(size as u64), + Helper::BitField(size, Some((offset, t))) => { 1 + static_int_str_len(*offset) + static_encoding_str_len(t, level.bitfield()) + static_int_str_len(size as u64) } - Indirection(kind, t) => 1 + static_encoding_str_len(t, level.indirection(kind)), - Array(len, item) => { + Helper::Indirection(kind, t) => 1 + static_encoding_str_len(t, level.indirection(kind)), + Helper::Array(len, item) => { 1 + static_int_str_len(len) + static_encoding_str_len(item, level.array()) + 1 } - Container(_, name, items) => { + Helper::Container(_, name, items) => { // Don't verify name here, we'll check it in `str_array` instead. + // This reduces the amount of post-mono errors the user will get. let mut res = 1 + name.len(); if let Some(level) = level.container_include_fields() { res += 1; @@ -68,107 +74,118 @@ pub(crate) const fn static_encoding_str_len(encoding: &Encoding, level: NestingL } res + 1 } - NoneInvalid => 0, + Helper::NoneInvalid => 0, } } +/// Encoding string as an array. +// TODO(MSRV 1.83): Write to `&mut [u8]` instead to avoid having to allocate +// an appropriately sized array at every usage site. pub(crate) const fn static_encoding_str_array( encoding: &Encoding, level: NestingLevel, ) -> [u8; LEN] { - use Helper::*; - let mut res: [u8; LEN] = [0; LEN]; let mut res_i = 0; match Helper::new(encoding) { - Primitive(primitive) => { + Helper::Primitive(primitive) => { let s = primitive.to_str().as_bytes(); let mut i = 0; while i < s.len() { + // Copy from `s` to `res`. + // This is a general pattern that's used a bunch below. res[i] = s[i]; i += 1; } } - BitField(size, None) => { + Helper::BitField(size, None) => { res[res_i] = b'b'; res_i += 1; - let mut i = 0; - // We use 3 even though it creates an oversized array + // We use 3 even though it creates an oversized array. let arr = static_int_str_array::<3>(size as u64); - while i < static_int_str_len(size as u64) { + let len = static_int_str_len(size as u64); + let mut i = 0; + while i < len { res[res_i] = arr[i]; res_i += 1; i += 1; } } - BitField(size, Some((offset, t))) => { + Helper::BitField(size, Some((offset, t))) => { let level = level.bitfield(); res[res_i] = b'b'; res_i += 1; - let mut i = 0; - // We use 20 even though it creates an oversized array + // We use 20 even though it creates an oversized array. let arr = static_int_str_array::<20>(*offset); - while i < static_int_str_len(*offset) { + let len = static_int_str_len(*offset); + let mut i = 0; + while i < len { res[res_i] = arr[i]; res_i += 1; i += 1; } - let mut i = 0; - // We use LEN even though it creates an oversized array - // This could probably be reduced to 1 + // We use LEN even though it creates an oversized array. + // This could probably be reduced to 1, do we need to support + // bitfields with arbitrary encodings? let arr = static_encoding_str_array::(t, level); - while i < static_encoding_str_len(t, level) { + let len = static_encoding_str_len(t, level); + let mut i = 0; + while i < len { res[res_i] = arr[i]; res_i += 1; i += 1; } - let mut i = 0; - // We use 3 even though it creates an oversized array + // We use 3 even though it creates an oversized array. let arr = static_int_str_array::<3>(size as u64); - while i < static_int_str_len(size as u64) { + let len = static_int_str_len(size as u64); + let mut i = 0; + while i < len { res[res_i] = arr[i]; res_i += 1; i += 1; } } - Indirection(kind, t) => { + Helper::Indirection(kind, t) => { let level = level.indirection(kind); res[res_i] = kind.prefix_byte(); res_i += 1; - let mut i = 0; - // We use LEN even though it creates an oversized array + // We use LEN even though it creates an oversized array. let arr = static_encoding_str_array::(t, level); - while i < static_encoding_str_len(t, level) { + let len = static_encoding_str_len(t, level); + let mut i = 0; + while i < len { res[res_i] = arr[i]; res_i += 1; i += 1; } } - Array(len, item) => { + Helper::Array(len, item) => { let level = level.array(); res[res_i] = b'['; res_i += 1; - let mut i = 0; - // We use 20 even though it creates an oversized array + // We use 20 even though it creates an oversized array. let arr = static_int_str_array::<20>(len); - while i < static_int_str_len(len) { + let len = static_int_str_len(len); + let mut i = 0; + while i < len { res[res_i] = arr[i]; res_i += 1; i += 1; } - let mut i = 0; - // We use LEN even though it creates an oversized array + // We use LEN even though it creates an oversized array. let arr = static_encoding_str_array::(item, level); - while i < static_encoding_str_len(item, level) { + let len = static_encoding_str_len(item, level); + let mut i = 0; + while i < len { res[res_i] = arr[i]; res_i += 1; i += 1; @@ -176,7 +193,7 @@ pub(crate) const fn static_encoding_str_array( res[res_i] = b']'; } - Container(kind, name, items) => { + Helper::Container(kind, name, items) => { if !verify_name(name) { match kind { ContainerKind::Struct => panic!("struct name was not a valid identifier"), @@ -187,8 +204,8 @@ pub(crate) const fn static_encoding_str_array( res[res_i] = kind.start_byte(); res_i += 1; - let mut name_i = 0; let name = name.as_bytes(); + let mut name_i = 0; while name_i < name.len() { res[res_i] = name[name_i]; res_i += 1; @@ -201,11 +218,11 @@ pub(crate) const fn static_encoding_str_array( let mut items_i = 0; while items_i < items.len() { - // We use LEN even though it creates an oversized array + // We use LEN even though it creates an oversized array. let field_res = static_encoding_str_array::(&items[items_i], level); - + let len = static_encoding_str_len(&items[items_i], level); let mut item_res_i = 0; - while item_res_i < static_encoding_str_len(&items[items_i], level) { + while item_res_i < len { res[res_i] = field_res[item_res_i]; res_i += 1; item_res_i += 1; @@ -216,13 +233,15 @@ pub(crate) const fn static_encoding_str_array( res[res_i] = kind.end_byte(); } - NoneInvalid => {} + Helper::NoneInvalid => {} }; res } #[cfg(test)] mod tests { + use std::string::ToString; + use super::*; macro_rules! const_int_str { @@ -240,6 +259,7 @@ mod tests { const STR_100: &str = const_int_str!(100); const STR_999: &str = const_int_str!(999); const STR_1236018655: &str = const_int_str!(1236018655); + const STR_MAX: &str = const_int_str!(u64::MAX); assert_eq!(STR_0, "0"); assert_eq!(STR_4, "4"); @@ -247,6 +267,15 @@ mod tests { assert_eq!(STR_100, "100"); assert_eq!(STR_999, "999"); assert_eq!(STR_1236018655, "1236018655"); + assert_eq!(STR_MAX, u64::MAX.to_string()); + } + + #[test] + fn test_str_len_max() { + assert_eq!(static_int_str_len(u8::MAX as _), 3); + assert_eq!(static_int_str_len(u16::MAX as _), 5); + assert_eq!(static_int_str_len(u32::MAX as _), 10); + assert_eq!(static_int_str_len(u64::MAX), 20); } // static encoding tests are in `encoding.rs` diff --git a/crates/objc2/tests/generic_const_exprs.rs b/crates/objc2/tests/generic_const_exprs.rs new file mode 100644 index 000000000..4e85c3bd5 --- /dev/null +++ b/crates/objc2/tests/generic_const_exprs.rs @@ -0,0 +1,37 @@ +//! If this ever starts compiling on stable, we should use/expose it! + +// Hack to make this work in CI (these features are only enabled when using +// the nightly compiler). +#![cfg(any( + feature = "unstable-darwin-objc", + feature = "unstable-autoreleasesafe", + feature = "unstable-arbitrary-self-types", + feature = "unstable-coerce-pointee", +))] +#![allow(incomplete_features)] // just a test +#![feature(generic_const_exprs)] + +use objc2::Encode; + +trait EncodingLen { + const ENCODING_LEN: usize; +} + +impl EncodingLen for T { + const ENCODING_LEN: usize = T::ENCODING.str_len(); +} + +pub trait EncodingExt: Encode +where + [(); Self::ENCODING_LEN]:, +{ + const ENCODING_ARRAY: [u8; Self::ENCODING_LEN] = Self::ENCODING.str_array(); + const ENCODING_STR: &str = unsafe { core::str::from_utf8_unchecked(&Self::ENCODING_ARRAY) }; +} + +impl EncodingExt for T where [(); Self::ENCODING_LEN]: {} + +#[test] +fn encoding_str() { + assert_eq!(<&i32>::ENCODING_STR, "^i"); +} diff --git a/crates/tests/src/test_encode_utils.rs b/crates/tests/src/test_encode_utils.rs index 2981f1e27..2d45fd2f3 100644 --- a/crates/tests/src/test_encode_utils.rs +++ b/crates/tests/src/test_encode_utils.rs @@ -16,8 +16,14 @@ unsafe fn assert_encoding(s: *const c_char, e: Encoding) { if !e.equivalent_to_str(s) { panic!("{} were not equivalent to {}", e, s); } + let expected_str = e.to_string(); // To ensure `equivalent_to_str` is implemented correctly: - assert_eq!(e.to_string(), s.trim_start_matches('r')); + assert_eq!(expected_str, s.trim_start_matches('r')); + // To ensure `str_array` is implemented correctly: + assert_eq!( + expected_str, + str::from_utf8(&e.str_array::<300>()[..e.str_len()]).unwrap() + ); } #[allow(unused)] From ace5af3b9ef78d1c1881e0a66d9c09a9c487645a Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Wed, 4 Mar 2026 17:09:36 +0100 Subject: [PATCH 2/2] Use static encoding strings in define_class! methods For optimization, and as a first step towards https://github.com/madsmtm/objc2/issues/604 --- crates/objc2/CHANGELOG.md | 1 + .../objc2/src/__macros/define_class/checks.rs | 39 +- .../src/__macros/define_class/encoding.rs | 91 +++++ .../objc2/src/__macros/define_class/ivars.rs | 17 +- crates/objc2/src/__macros/define_class/mod.rs | 2 + .../__macros/define_class/register_impls.rs | 22 +- .../objc2/src/__macros/define_class/thunk.rs | 19 + crates/objc2/src/__macros/mod.rs | 7 +- crates/objc2/src/runtime/define.rs | 60 ++- crates/objc2/src/runtime/mod.rs | 2 + .../expected/apple-aarch64.s | 35 +- .../expected/apple-x86_64.s | 31 +- .../expected/apple-aarch64.s | 18 +- .../expected/apple-x86_64.s | 16 +- .../expected/apple-aarch64.s | 356 ++++++++---------- .../expected/apple-x86_64.s | 130 +++---- .../ui/define_class_invalid_receiver.stderr | 18 +- ...s_invalid_receiver_retain_semantics.stderr | 4 +- .../ui/define_class_invalid_type.stderr | 6 +- .../ui/define_class_invalid_type2.stderr | 4 +- .../ui/define_class_invalid_type3.stderr | 6 +- .../define_class_mut_self_not_mutable.stderr | 4 +- 22 files changed, 499 insertions(+), 389 deletions(-) create mode 100644 crates/objc2/src/__macros/define_class/encoding.rs diff --git a/crates/objc2/CHANGELOG.md b/crates/objc2/CHANGELOG.md index 99a1cbb72..7b336e382 100644 --- a/crates/objc2/CHANGELOG.md +++ b/crates/objc2/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Added support for `&CStr` in method argument and return types. * Implement `Encode` on `Result<(), T>` when `T: OptionEncode`. * Allow returning `Result>` from `define_class!`. +* Optimized adding `define_class!` methods to avoid a few string allocations. ## Changed * **BREAKING**: Changed syntax for `define_class!` ivars (instance variables). diff --git a/crates/objc2/src/__macros/define_class/checks.rs b/crates/objc2/src/__macros/define_class/checks.rs index 065e3a128..7e1b4a390 100644 --- a/crates/objc2/src/__macros/define_class/checks.rs +++ b/crates/objc2/src/__macros/define_class/checks.rs @@ -6,6 +6,7 @@ use core::panic::{RefUnwindSafe, UnwindSafe}; #[cfg(debug_assertions)] use std::collections::HashSet; +use crate::encode::{EncodeArguments, EncodeReturn}; use crate::runtime::{AnyClass, ClassBuilder, MethodImplementation, Sel}; #[cfg(debug_assertions)] use crate::runtime::{AnyProtocol, MethodDescription}; @@ -215,21 +216,43 @@ impl ClassBuilderHelper { // Addition: This restricts to callee `T` #[inline] - pub unsafe fn add_method(&mut self, sel: Sel, func: F) + pub unsafe fn add_method(&mut self, sel: Sel, func: F, encoding: &CStr) where F: MethodImplementation, { + if cfg!(all( + debug_assertions, + not(feature = "disable-encoding-assertions") + )) { + self.builder + .verify_method(sel, F::Arguments::ENCODINGS, &F::Return::ENCODING_RETURN); + } + // SAFETY: Checked by caller - unsafe { self.builder.add_method(sel, func) } + unsafe { self.builder.add_method_inner(sel, func.__imp(), encoding) } } #[inline] - pub unsafe fn add_class_method(&mut self, sel: Sel, func: F) + pub unsafe fn add_class_method(&mut self, sel: Sel, func: F, encoding: &CStr) where F: MethodImplementation, { + if cfg!(all( + debug_assertions, + not(feature = "disable-encoding-assertions") + )) { + self.builder.verify_class_method( + sel, + F::Arguments::ENCODINGS, + &F::Return::ENCODING_RETURN, + ); + } + // SAFETY: Checked by caller - unsafe { self.builder.add_class_method(sel, func) } + unsafe { + self.builder + .add_class_method_inner(sel, func.__imp(), encoding) + } } } @@ -259,7 +282,7 @@ pub struct ClassProtocolMethodsBuilder<'a, T: ?Sized> { impl ClassProtocolMethodsBuilder<'_, T> { // Addition: This restricts to callee `T` #[inline] - pub unsafe fn add_method(&mut self, sel: Sel, func: F) + pub unsafe fn add_method(&mut self, sel: Sel, func: F, encoding: &CStr) where F: MethodImplementation, { @@ -279,7 +302,7 @@ impl ClassProtocolMethodsBuilder<'_, T> { } // SAFETY: Checked by caller - unsafe { self.builder.add_method(sel, func) }; + unsafe { self.builder.add_method(sel, func, encoding) }; #[cfg(debug_assertions)] if !self.registered_instance_methods.insert(sel) { @@ -288,7 +311,7 @@ impl ClassProtocolMethodsBuilder<'_, T> { } #[inline] - pub unsafe fn add_class_method(&mut self, sel: Sel, func: F) + pub unsafe fn add_class_method(&mut self, sel: Sel, func: F, encoding: &CStr) where F: MethodImplementation, { @@ -308,7 +331,7 @@ impl ClassProtocolMethodsBuilder<'_, T> { } // SAFETY: Checked by caller - unsafe { self.builder.add_class_method(sel, func) }; + unsafe { self.builder.add_class_method(sel, func, encoding) }; #[cfg(debug_assertions)] if !self.registered_class_methods.insert(sel) { diff --git a/crates/objc2/src/__macros/define_class/encoding.rs b/crates/objc2/src/__macros/define_class/encoding.rs new file mode 100644 index 000000000..770278e47 --- /dev/null +++ b/crates/objc2/src/__macros/define_class/encoding.rs @@ -0,0 +1,91 @@ +//! Helpers to construct encoding strings for methods at `const`-time. +use objc2_encode::Encoding; + +pub const fn method_encoding_str_len(ret: &Encoding, args: &[Encoding]) -> usize { + let mut len = 0; + len += ret.str_len(); + len += 1; // Encoding::Object + len += 1; // Encoding::Sel + let mut i = 0; + while i < args.len() { + len += args[i].str_len(); + i += 1; + } + len +} + +pub const fn method_encoding_str_array( + ret: &Encoding, + args: &[Encoding], +) -> [u8; LEN] { + let mut res: [u8; LEN] = [0; LEN]; + let mut res_i = 0; + + let mut i = 0; + // We use LEN even though it creates an oversized array. + let arr = ret.str_array::(); + while i < ret.str_len() { + res[res_i] = arr[i]; + i += 1; + res_i += 1; + } + + // Encoding::Object + res[res_i] = b'@'; + res_i += 1; + + // Encoding::Sel + res[res_i] = b':'; + res_i += 1; + + let mut i = 0; + while i < args.len() { + let mut j = 0; + // We use LEN even though it creates an oversized array. + let arr = args[i].str_array::(); + while j < args[i].str_len() { + res[res_i] = arr[j]; + j += 1; + res_i += 1; + } + i += 1; + } + res +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::encode::{Encode, EncodeReturn}; + use crate::runtime::{method_type_encoding, Bool, NSObject}; + + #[track_caller] + fn check(ret: &Encoding, args: &[Encoding]) { + // Compare against reference impl + let expected = method_type_encoding(ret, args).into_string().unwrap(); + + let len = method_encoding_str_len(ret, args); + assert_eq!(expected.len(), len, "incorrect length"); + assert!(len < 100); + + let arr = method_encoding_str_array::<100>(ret, args); + let (s, rest) = arr.split_at(len); + let s = str::from_utf8(s).unwrap(); + assert_eq!(expected, s, "incorrect output: {arr:?}"); + + assert!(rest.iter().all(|x| *x == 0), "rest must be zero: {arr:?}"); + } + + #[test] + fn various() { + check(&<()>::ENCODING_RETURN, &[]); + check( + &<*const NSObject>::ENCODING_RETURN, + &[<&NSObject>::ENCODING], + ); + check( + &<&&&&&&i32>::ENCODING_RETURN, + &[<&&&&&&NSObject>::ENCODING, <&&&&&&Bool>::ENCODING], + ); + } +} diff --git a/crates/objc2/src/__macros/define_class/ivars.rs b/crates/objc2/src/__macros/define_class/ivars.rs index f75dbdec7..870d466fa 100644 --- a/crates/objc2/src/__macros/define_class/ivars.rs +++ b/crates/objc2/src/__macros/define_class/ivars.rs @@ -52,8 +52,11 @@ use core::ffi::CStr; use core::mem; use core::ptr::{self, NonNull}; +use crate::__macros::{method_encoding_str_array, method_encoding_str_len}; use crate::encode::{Encode, Encoding}; -use crate::runtime::{AnyClass, AnyObject, ClassBuilder, MessageReceiver, Sel}; +use crate::runtime::{ + AnyClass, AnyObject, ClassBuilder, MessageReceiver, MethodImplementation, Sel, +}; use crate::{sel, ClassType, DefinedClass}; /// A type representing the drop flags that may be set for a type. @@ -144,9 +147,15 @@ where // Add dealloc if the class or the ivars need dropping. if mem::needs_drop::() || mem::needs_drop::() { let func: unsafe extern "C-unwind" fn(_, _) = dealloc::; - // SAFETY: The function signature is correct, and method contract is - // upheld inside `dealloc`. - unsafe { builder.add_method(sel!(dealloc), func) }; + + const ENCODING_LEN: usize = method_encoding_str_len(&Encoding::Void, &[]); + const ENCODING_ARRAY: [u8; ENCODING_LEN + 1] = + method_encoding_str_array::<{ ENCODING_LEN + 1 }>(&Encoding::Void, &[]); + const ENCODING: &CStr = unsafe { CStr::from_bytes_with_nul_unchecked(&ENCODING_ARRAY) }; + + // SAFETY: The function signature is correct, the encoding is correct, + // and method contract is upheld inside `dealloc`. + unsafe { builder.add_method_inner(sel!(dealloc), func.__imp(), ENCODING) }; } else { // Users should not rely on this omission, it is only an optimization. } diff --git a/crates/objc2/src/__macros/define_class/mod.rs b/crates/objc2/src/__macros/define_class/mod.rs index d77e8da6b..0e95b9ca1 100644 --- a/crates/objc2/src/__macros/define_class/mod.rs +++ b/crates/objc2/src/__macros/define_class/mod.rs @@ -1,10 +1,12 @@ mod checks; +mod encoding; mod ivars; mod output_impls; mod register_impls; mod thunk; pub use self::checks::*; +pub use self::encoding::*; pub use self::ivars::*; pub use self::thunk::*; diff --git a/crates/objc2/src/__macros/define_class/register_impls.rs b/crates/objc2/src/__macros/define_class/register_impls.rs index 8804cadd8..41e56508e 100644 --- a/crates/objc2/src/__macros/define_class/register_impls.rs +++ b/crates/objc2/src/__macros/define_class/register_impls.rs @@ -348,12 +348,28 @@ macro_rules! __declare_class_register_thunk { // TODO: `` once we emit on protocols. } + const __ENCODING_LEN: $crate::__macros::usize = $crate::__macros::method_encoding_str_len( + &<$for as $crate::__macros::ConvertDefinedFn<'_, __FnMarker, __RetainSemantics, __Kind<'_>>>::RETURN_ENCODING, + <$for as $crate::__macros::ConvertDefinedFn<'_, __FnMarker, __RetainSemantics, __Kind<'_>>>::ARGUMENT_ENCODINGS, + ); + + // SAFETY: The array is guaranteed to be contain no interior NUL + // bytes (`verify_name` in `objc2-encode`), and a NUL byte at the end + // because we specify `__ENCODING_LEN + 1`. + const __ENCODING: &$crate::__macros::CStr = unsafe { + $crate::__macros::CStr::from_bytes_with_nul_unchecked(&$crate::__macros::method_encoding_str_array::<{__ENCODING_LEN + 1}>( + &<$for as $crate::__macros::ConvertDefinedFn<'_, __FnMarker, __RetainSemantics, __Kind<'_>>>::RETURN_ENCODING, + <$for as $crate::__macros::ConvertDefinedFn<'_, __FnMarker, __RetainSemantics, __Kind<'_>>>::ARGUMENT_ENCODINGS, + )) + }; + unsafe { $crate::__declare_class_call_builder_method! { ($builder) ($crate::sel!($($sel)*)) (>>::THUNK) ($($receiver_ty)?) + (__ENCODING) } }; ); @@ -385,8 +401,9 @@ macro_rules! __declare_class_call_builder_method { ($sel:expr) ($fnptr:expr) () + ($encoding:expr) } => { - $builder.add_class_method($sel, $fnptr) + $builder.add_class_method($sel, $fnptr, $encoding) }; // Instance method @@ -395,8 +412,9 @@ macro_rules! __declare_class_call_builder_method { ($sel:expr) ($fnptr:expr) ($_receiver_ty:ty) + ($encoding:expr) } => { - $builder.add_method($sel, $fnptr) + $builder.add_method($sel, $fnptr, $encoding) }; } diff --git a/crates/objc2/src/__macros/define_class/thunk.rs b/crates/objc2/src/__macros/define_class/thunk.rs index 084f3f4d6..ad6f2a522 100644 --- a/crates/objc2/src/__macros/define_class/thunk.rs +++ b/crates/objc2/src/__macros/define_class/thunk.rs @@ -20,7 +20,10 @@ //! few arguments compared to the selector. use core::marker::PhantomData; +use objc2_encode::Encoding; + use super::super::{ConvertArgument, ConvertError, KindDefined, RetainSemantics}; +use crate::encode::{EncodeArguments, EncodeReturn}; use crate::rc::Retained; use crate::runtime::{MethodImplementation, Sel}; use crate::ClassType; @@ -49,6 +52,22 @@ pub trait ConvertDefinedFn<'f, FnMarker, MethodFamily, Kind>: ClassType { /// The generated thunk. const THUNK: >::ExternFn = { Self::Func::THUNK }; + + /// Helper for getting the return encoding of the extern function. + const RETURN_ENCODING: Encoding = <<>::ExternFn as MethodImplementation>::Return as EncodeReturn>::ENCODING_RETURN; + + /// Helper for getting the argument encodings of the extern function. + const ARGUMENT_ENCODINGS: &'static [Encoding] = <<>::ExternFn as MethodImplementation>::Arguments as EncodeArguments>::ENCODINGS; } /// Function pointers that can be converted to `extern "C-unwind"` function diff --git a/crates/objc2/src/__macros/mod.rs b/crates/objc2/src/__macros/mod.rs index a2d2e2958..8418b95df 100644 --- a/crates/objc2/src/__macros/mod.rs +++ b/crates/objc2/src/__macros/mod.rs @@ -47,7 +47,7 @@ pub use core::marker::{PhantomData, Sized}; pub use core::mem::{size_of, transmute, ManuallyDrop, MaybeUninit}; pub use core::ops::Deref; pub use core::option::Option::{self, None, Some}; -pub use core::primitive::{bool, isize, str, u8}; +pub use core::primitive::{bool, isize, str, u8, usize}; pub use core::{compile_error, concat, env, module_path, panic, stringify}; pub use std::sync::Once; @@ -60,8 +60,9 @@ pub use self::convert::{ ConvertArgument, ConvertArguments, ConvertError, ConvertReturn, TupleExtender, }; pub use self::define_class::{ - class_c_name, define_class, ClassBuilderHelper, ClassFnKind, ClassFnResultKind, - ClassProtocolMethodsBuilder, ConvertDefinedFn, DefinedIvarsHelper, LifetimeAssign, MethodKind, + class_c_name, define_class, method_encoding_str_array, method_encoding_str_len, + ClassBuilderHelper, ClassFnKind, ClassFnResultKind, ClassProtocolMethodsBuilder, + ConvertDefinedFn, DefinedIvarsHelper, FnToExternFn, LifetimeAssign, MethodKind, MethodResultKind, ThreadKindAutoTraits, }; pub use self::extern_class::{DoesNotImplDrop, MainThreadOnlyDoesNotImplSendSync, ValidThreadKind}; diff --git a/crates/objc2/src/runtime/define.rs b/crates/objc2/src/runtime/define.rs index 01a80d20f..4f1010d7f 100644 --- a/crates/objc2/src/runtime/define.rs +++ b/crates/objc2/src/runtime/define.rs @@ -14,7 +14,8 @@ use crate::runtime::{AnyClass, AnyObject, AnyProtocol, Bool, Imp, MethodImplemen use crate::sel; use crate::Message; -fn method_type_encoding(ret: &Encoding, args: &[Encoding]) -> CString { +// Used in tests +pub(crate) fn method_type_encoding(ret: &Encoding, args: &[Encoding]) -> CString { // First two arguments are always self and the selector let mut types = format!("{ret}{}{}", <*mut AnyObject>::ENCODING, Sel::ENCODING); for enc in args { @@ -256,7 +257,7 @@ impl ClassBuilder { F: MethodImplementation, { unsafe { - self.add_method_inner( + self.add_method_mono( sel, F::Arguments::ENCODINGS, &F::Return::ENCODING_RETURN, @@ -265,7 +266,7 @@ impl ClassBuilder { } } - unsafe fn add_method_inner( + unsafe fn add_method_mono( &mut self, sel: Sel, enc_args: &[Encoding], @@ -280,9 +281,22 @@ impl ClassBuilder { enc_args.len(), ); - // Verify that, if the method is present on the superclass, that the - // encoding is correct. - #[cfg(all(debug_assertions, not(feature = "disable-encoding-assertions")))] + if cfg!(all( + debug_assertions, + not(feature = "disable-encoding-assertions") + )) { + self.verify_method(sel, enc_args, enc_ret); + } + + let encoding = method_type_encoding(enc_ret, enc_args); + + // SAFETY: The encoding is correct, and the rest is upheld by the caller. + unsafe { self.add_method_inner(sel, func, &encoding) } + } + + // Verify that, if the method is present on the superclass, that the + // encoding is correct. + pub(crate) fn verify_method(&self, sel: Sel, enc_args: &[Encoding], enc_ret: &Encoding) { if let Some(superclass) = self.superclass() { if let Some(method) = superclass.instance_method(sel) { if let Err(err) = super::verify::verify_method_signature(method, enc_args, enc_ret) @@ -294,9 +308,11 @@ impl ClassBuilder { } } } + } - let types = method_type_encoding(enc_ret, enc_args); - let success = unsafe { ffi::class_addMethod(self.as_mut_ptr(), sel, func, types.as_ptr()) }; + pub(crate) unsafe fn add_method_inner(&mut self, sel: Sel, func: Imp, encoding: &CStr) { + let success = + unsafe { ffi::class_addMethod(self.as_mut_ptr(), sel, func, encoding.as_ptr()) }; assert!(success.as_bool(), "failed to add method {sel}"); } @@ -321,7 +337,7 @@ impl ClassBuilder { F: MethodImplementation, { unsafe { - self.add_class_method_inner( + self.add_class_method_mono( sel, F::Arguments::ENCODINGS, &F::Return::ENCODING_RETURN, @@ -330,7 +346,7 @@ impl ClassBuilder { } } - unsafe fn add_class_method_inner( + unsafe fn add_class_method_mono( &mut self, sel: Sel, enc_args: &[Encoding], @@ -345,9 +361,22 @@ impl ClassBuilder { enc_args.len(), ); - // Verify that, if the method is present on the superclass, that the - // encoding is correct. - #[cfg(all(debug_assertions, not(feature = "disable-encoding-assertions")))] + if cfg!(all( + debug_assertions, + not(feature = "disable-encoding-assertions") + )) { + self.verify_class_method(sel, enc_args, enc_ret); + } + + let encoding = method_type_encoding(enc_ret, enc_args); + + // SAFETY: The encoding is correct, and the rest is upheld by the caller. + unsafe { self.add_class_method_inner(sel, func, &encoding) } + } + + // Verify that, if the method is present on the superclass, that the + // encoding is correct. + pub(crate) fn verify_class_method(&self, sel: Sel, enc_args: &[Encoding], enc_ret: &Encoding) { if let Some(superclass) = self.superclass() { if let Some(method) = superclass.class_method(sel) { if let Err(err) = super::verify::verify_method_signature(method, enc_args, enc_ret) @@ -359,10 +388,11 @@ impl ClassBuilder { } } } + } - let types = method_type_encoding(enc_ret, enc_args); + pub(crate) unsafe fn add_class_method_inner(&mut self, sel: Sel, func: Imp, encoding: &CStr) { let success = - unsafe { ffi::class_addMethod(self.metaclass_mut(), sel, func, types.as_ptr()) }; + unsafe { ffi::class_addMethod(self.metaclass_mut(), sel, func, encoding.as_ptr()) }; assert!(success.as_bool(), "failed to add class method {sel}"); } diff --git a/crates/objc2/src/runtime/mod.rs b/crates/objc2/src/runtime/mod.rs index 5ff68756f..2167a2a3d 100644 --- a/crates/objc2/src/runtime/mod.rs +++ b/crates/objc2/src/runtime/mod.rs @@ -107,6 +107,8 @@ pub use self::verify::VerificationError; #[allow(deprecated)] pub use crate::ffi::{BOOL, NO, YES}; +#[cfg(test)] +pub(crate) use self::define::method_type_encoding; pub(crate) use self::malloc::{MallocCStr, MallocSlice}; pub(crate) use self::method::MethodDescription; pub(crate) use self::method_encoding_iter::{EncodingParseError, MethodEncodingIter}; diff --git a/crates/test-assembly/crates/test_define_class_drop_ivars/expected/apple-aarch64.s b/crates/test-assembly/crates/test_define_class_drop_ivars/expected/apple-aarch64.s index 1ec4f938e..671d23c27 100644 --- a/crates/test-assembly/crates/test_define_class_drop_ivars/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_define_class_drop_ivars/expected/apple-aarch64.s @@ -141,16 +141,15 @@ Lloh14: ldr x1, [x8] Ltmp6: Lloh15: - adrp x4, l_anon.[ID].3@PAGE + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::ivars::dealloc::, 0)@PAGE Lloh16: - add x4, x4, l_anon.[ID].3@PAGEOFF + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::ivars::dealloc::, 0)@PAGEOFF Lloh17: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::ivars::dealloc::, 0)@PAGE + adrp x3, l_anon.[ID].3@PAGE Lloh18: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::ivars::dealloc::, 0)@PAGEOFF + add x3, x3, l_anon.[ID].3@PAGEOFF mov x0, sp - mov w2, #8 - mov x3, #0 + mov w4, #4 bl SYM(::add_method_inner, 0) Ltmp7: Lloh19: @@ -161,16 +160,15 @@ Lloh21: ldr x1, [x8] Ltmp8: Lloh22: - adrp x4, l_anon.[ID].8@PAGE + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_drop_ivars[CRATE_ID]::DropIvars>, 0)@PAGE Lloh23: - add x4, x4, l_anon.[ID].8@PAGEOFF + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_drop_ivars[CRATE_ID]::DropIvars>, 0)@PAGEOFF Lloh24: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_drop_ivars[CRATE_ID]::DropIvars>, 0)@PAGE + adrp x3, l_anon.[ID].8@PAGE Lloh25: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_drop_ivars[CRATE_ID]::DropIvars>, 0)@PAGEOFF + add x3, x3, l_anon.[ID].8@PAGEOFF mov x0, sp - mov w2, #8 - mov x3, #0 + mov w4, #4 bl SYM(::add_method_inner, 0) Ltmp9: mov w8, #2 @@ -607,12 +605,10 @@ l_anon.[ID].1: l_anon.[ID].2: .asciz "drop_flag" - .section __TEXT,__const - .p2align 3, 0x0 l_anon.[ID].3: - .byte 19 - .space 39 + .asciz "v@:" + .section __TEXT,__const .p2align 3, 0x0 l_anon.[ID].4: .byte 10 @@ -633,13 +629,10 @@ l_anon.[ID].7: .quad l_anon.[ID].6 .asciz "p\000\000\000\000\000\000\000\237\000\000\0002\000\000" - .section __TEXT,__const - .p2align 3, 0x0 + .section __TEXT,__cstring,cstring_literals l_anon.[ID].8: - .byte 21 - .space 39 + .asciz "@@:" - .section __TEXT,__cstring,cstring_literals l_anon.[ID].9: .asciz "DropIvars" diff --git a/crates/test-assembly/crates/test_define_class_drop_ivars/expected/apple-x86_64.s b/crates/test-assembly/crates/test_define_class_drop_ivars/expected/apple-x86_64.s index 33d93349b..8586c9d1c 100644 --- a/crates/test-assembly/crates/test_define_class_drop_ivars/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_define_class_drop_ivars/expected/apple-x86_64.s @@ -128,21 +128,19 @@ Lfunc_begin1: mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_dealloc@GOTPCREL] mov rsi, qword ptr [rax] Ltmp6: - lea r8, [rip + l_anon.[ID].3] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::ivars::dealloc::, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::ivars::dealloc::, 0)] + lea rcx, [rip + L_anon.[ID].3] lea rdi, [rbp - 24] - mov edx, 8 - xor ecx, ecx + mov r8d, 4 call SYM(::add_method_inner, 0) Ltmp7: mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] mov rsi, qword ptr [rax] Ltmp8: - lea r8, [rip + l_anon.[ID].8] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_drop_ivars[CRATE_ID]::DropIvars>, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_drop_ivars[CRATE_ID]::DropIvars>, 0)] + lea rcx, [rip + L_anon.[ID].8] lea rdi, [rbp - 24] - mov edx, 8 - xor ecx, ecx + mov r8d, 4 call SYM(::add_method_inner, 0) Ltmp9: mov qword ptr [rbp - 56], 2 @@ -472,12 +470,10 @@ L_anon.[ID].1: L_anon.[ID].2: .asciz "drop_flag" - .section __TEXT,__const - .p2align 3, 0x0 -l_anon.[ID].3: - .byte 19 - .space 39 +L_anon.[ID].3: + .asciz "v@:" + .section __TEXT,__const .p2align 3, 0x0 l_anon.[ID].4: .byte 10 @@ -498,13 +494,10 @@ l_anon.[ID].7: .quad L_anon.[ID].6 .asciz "p\000\000\000\000\000\000\000\237\000\000\0002\000\000" - .section __TEXT,__const - .p2align 3, 0x0 -l_anon.[ID].8: - .byte 21 - .space 39 - .section __TEXT,__cstring,cstring_literals +L_anon.[ID].8: + .asciz "@@:" + L_anon.[ID].9: .asciz "DropIvars" diff --git a/crates/test-assembly/crates/test_define_class_forgetable_ivars/expected/apple-aarch64.s b/crates/test-assembly/crates/test_define_class_forgetable_ivars/expected/apple-aarch64.s index 114ad6b1a..1b64bdecc 100644 --- a/crates/test-assembly/crates/test_define_class_forgetable_ivars/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_define_class_forgetable_ivars/expected/apple-aarch64.s @@ -71,16 +71,15 @@ Lloh15: ldr x1, [x8] Ltmp0: Lloh16: - adrp x4, l_anon.[ID].5@PAGE + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_forgetable_ivars[CRATE_ID]::ForgetableIvars>, 0)@PAGE Lloh17: - add x4, x4, l_anon.[ID].5@PAGEOFF + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_forgetable_ivars[CRATE_ID]::ForgetableIvars>, 0)@PAGEOFF Lloh18: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_forgetable_ivars[CRATE_ID]::ForgetableIvars>, 0)@PAGE + adrp x3, l_anon.[ID].5@PAGE Lloh19: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_forgetable_ivars[CRATE_ID]::ForgetableIvars>, 0)@PAGEOFF + add x3, x3, l_anon.[ID].5@PAGEOFF mov x0, sp - mov w2, #8 - mov x3, #0 + mov w4, #4 bl SYM(::add_method_inner, 0) Ltmp1: mov w8, #2 @@ -378,13 +377,10 @@ l_anon.[ID].4: .quad l_anon.[ID].3 .asciz "p\000\000\000\000\000\000\000\237\000\000\0002\000\000" - .section __TEXT,__const - .p2align 3, 0x0 + .section __TEXT,__cstring,cstring_literals l_anon.[ID].5: - .byte 21 - .space 39 + .asciz "@@:" - .section __TEXT,__cstring,cstring_literals l_anon.[ID].6: .asciz "ForgetableIvars" diff --git a/crates/test-assembly/crates/test_define_class_forgetable_ivars/expected/apple-x86_64.s b/crates/test-assembly/crates/test_define_class_forgetable_ivars/expected/apple-x86_64.s index da167be18..a0d50b29f 100644 --- a/crates/test-assembly/crates/test_define_class_forgetable_ivars/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_define_class_forgetable_ivars/expected/apple-x86_64.s @@ -46,11 +46,10 @@ Lfunc_begin0: mov rax, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_init@GOTPCREL] mov rsi, qword ptr [rax] Ltmp0: - lea r8, [rip + l_anon.[ID].5] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_forgetable_ivars[CRATE_ID]::ForgetableIvars>, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, objc2[CRATE_ID]::rc::allocated_partial_init::Allocated, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<3u8>, test_define_class_forgetable_ivars[CRATE_ID]::ForgetableIvars>, 0)] + lea rcx, [rip + L_anon.[ID].5] lea rdi, [rbp - 16] - mov edx, 8 - xor ecx, ecx + mov r8d, 4 call SYM(::add_method_inner, 0) Ltmp1: mov qword ptr [rbp - 48], 2 @@ -248,13 +247,10 @@ l_anon.[ID].4: .quad L_anon.[ID].3 .asciz "p\000\000\000\000\000\000\000\237\000\000\0002\000\000" - .section __TEXT,__const - .p2align 3, 0x0 -l_anon.[ID].5: - .byte 21 - .space 39 - .section __TEXT,__cstring,cstring_literals +L_anon.[ID].5: + .asciz "@@:" + L_anon.[ID].6: .asciz "ForgetableIvars" diff --git a/crates/test-assembly/crates/test_define_class_no_ivars/expected/apple-aarch64.s b/crates/test-assembly/crates/test_define_class_no_ivars/expected/apple-aarch64.s index e2ee4cd9d..fd0db2df6 100644 --- a/crates/test-assembly/crates/test_define_class_no_ivars/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_define_class_no_ivars/expected/apple-aarch64.s @@ -29,9 +29,9 @@ Lloh6: Lloh7: add x3, x3, l_anon.[ID].0@PAGEOFF Lloh8: - adrp x4, l_anon.[ID].14@PAGE + adrp x4, l_anon.[ID].13@PAGE Lloh9: - add x4, x4, l_anon.[ID].14@PAGEOFF + add x4, x4, l_anon.[ID].13@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(::call, 0) @@ -169,9 +169,9 @@ Lloh21: Lloh22: add x3, x3, l_anon.[ID].0@PAGEOFF Lloh23: - adrp x4, l_anon.[ID].14@PAGE + adrp x4, l_anon.[ID].13@PAGE Lloh24: - add x4, x4, l_anon.[ID].14@PAGEOFF + add x4, x4, l_anon.[ID].13@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(::call, 0) @@ -225,9 +225,9 @@ Lloh34: Lloh35: add x3, x3, l_anon.[ID].0@PAGEOFF Lloh36: - adrp x4, l_anon.[ID].14@PAGE + adrp x4, l_anon.[ID].13@PAGE Lloh37: - add x4, x4, l_anon.[ID].14@PAGEOFF + add x4, x4, l_anon.[ID].13@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(::call, 0) @@ -263,9 +263,9 @@ Lloh39: Lloh40: ldr x0, [x8] Lloh41: - adrp x1, l_anon.[ID].12@PAGE + adrp x1, l_anon.[ID].11@PAGE Lloh42: - add x1, x1, l_anon.[ID].12@PAGEOFF + add x1, x1, l_anon.[ID].11@PAGEOFF mov x2, #0 bl _objc_allocateClassPair cbz x0, LBB6_16 @@ -276,16 +276,15 @@ Lloh44: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_a9fb958c74006297@PAGEOFF] Ltmp6: Lloh45: - adrp x4, l_anon.[ID].3@PAGE + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGE Lloh46: - add x4, x4, l_anon.[ID].3@PAGEOFF + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGEOFF Lloh47: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGE + adrp x3, l_anon.[ID].3@PAGE Lloh48: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGEOFF + add x3, x3, l_anon.[ID].3@PAGEOFF add x0, sp, #8 - mov w2, #8 - mov x3, #0 + mov w4, #4 bl SYM(::add_class_method_inner, 0) Ltmp7: Lloh49: @@ -294,16 +293,15 @@ Lloh50: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_adfe2eb45443b755@PAGEOFF] Ltmp8: Lloh51: - adrp x4, l_anon.[ID].4@PAGE + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, (), objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGE Lloh52: - add x4, x4, l_anon.[ID].4@PAGEOFF + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, (), objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGEOFF Lloh53: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, (), objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGE + adrp x3, l_anon.[ID].4@PAGE Lloh54: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, (), objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGEOFF + add x3, x3, l_anon.[ID].4@PAGEOFF add x0, sp, #8 - mov w2, #8 - mov x3, #0 + mov w4, #4 bl SYM(::add_method_inner, 0) Ltmp9: Lloh55: @@ -312,16 +310,15 @@ Lloh56: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_71045e8f6bc4d4f9@PAGEOFF] Ltmp10: Lloh57: - adrp x2, l_anon.[ID].5@PAGE + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, bool, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)@PAGE Lloh58: - add x2, x2, l_anon.[ID].5@PAGEOFF + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, bool, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)@PAGEOFF Lloh59: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, bool, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)@PAGE + adrp x3, l_anon.[ID].5@PAGE Lloh60: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, bool, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)@PAGEOFF + add x3, x3, l_anon.[ID].5@PAGEOFF add x0, sp, #8 - mov w3, #1 - mov x4, x2 + mov w4, #5 bl SYM(::add_method_inner, 0) Ltmp11: Lloh61: @@ -330,16 +327,15 @@ Lloh62: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_44ec46acb208c3d4@PAGEOFF] Ltmp12: Lloh63: - adrp x4, l_anon.[ID].6@PAGE + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGE Lloh64: - add x4, x4, l_anon.[ID].6@PAGEOFF + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGEOFF Lloh65: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGE + adrp x3, l_anon.[ID].6@PAGE Lloh66: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)@PAGEOFF + add x3, x3, l_anon.[ID].6@PAGEOFF add x0, sp, #8 - mov w2, #8 - mov x3, #0 + mov w4, #4 bl SYM(::add_method_inner, 0) Ltmp13: Lloh67: @@ -348,26 +344,22 @@ Lloh68: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_d63b759d5c7ed4f0@PAGEOFF] Ltmp14: Lloh69: - adrp x2, l_anon.[ID].5@PAGE + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)@PAGE Lloh70: - add x2, x2, l_anon.[ID].5@PAGEOFF + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)@PAGEOFF Lloh71: - adrp x4, l_anon.[ID].6@PAGE + adrp x3, l_anon.[ID].7@PAGE Lloh72: - add x4, x4, l_anon.[ID].6@PAGEOFF -Lloh73: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)@PAGE -Lloh74: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)@PAGEOFF + add x3, x3, l_anon.[ID].7@PAGEOFF add x0, sp, #8 - mov w3, #1 + mov w4, #5 bl SYM(::add_method_inner, 0) Ltmp15: Ltmp16: -Lloh75: - adrp x0, l_anon.[ID].7@PAGE -Lloh76: - add x0, x0, l_anon.[ID].7@PAGEOFF +Lloh73: + adrp x0, l_anon.[ID].8@PAGE +Lloh74: + add x0, x0, l_anon.[ID].8@PAGEOFF mov w1, #8 bl SYM(objc2[CRATE_ID]::top_level_traits::get_protocol, 0) mov x1, x0 @@ -377,10 +369,10 @@ Ltmp17: bl _class_addProtocol LBB6_10: Ltmp18: -Lloh77: - adrp x0, l_anon.[ID].8@PAGE -Lloh78: - add x0, x0, l_anon.[ID].8@PAGEOFF +Lloh75: + adrp x0, l_anon.[ID].9@PAGE +Lloh76: + add x0, x0, l_anon.[ID].9@PAGEOFF mov w1, #9 bl SYM(objc2[CRATE_ID]::top_level_traits::get_protocol, 0) mov x1, x0 @@ -389,25 +381,21 @@ Ltmp19: ldr x0, [sp, #8] bl _class_addProtocol LBB6_13: -Lloh79: +Lloh77: adrp x8, L_OBJC_SELECTOR_REFERENCES_996a3b5043cf563d@PAGE -Lloh80: +Lloh78: ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_996a3b5043cf563d@PAGEOFF] Ltmp20: +Lloh79: + adrp x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<4u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, *const objc2[CRATE_ID]::runtime::nszone::NSZone>, 0)@PAGE +Lloh80: + add x2, x2, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<4u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, *const objc2[CRATE_ID]::runtime::nszone::NSZone>, 0)@PAGEOFF Lloh81: - adrp x2, l_anon.[ID].11@PAGE + adrp x3, l_anon.[ID].10@PAGE Lloh82: - add x2, x2, l_anon.[ID].11@PAGEOFF -Lloh83: - adrp x4, l_anon.[ID].6@PAGE -Lloh84: - add x4, x4, l_anon.[ID].6@PAGEOFF -Lloh85: - adrp x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<4u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, *const objc2[CRATE_ID]::runtime::nszone::NSZone>, 0)@PAGE -Lloh86: - add x5, x5, SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<4u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, *const objc2[CRATE_ID]::runtime::nszone::NSZone>, 0)@PAGEOFF + add x3, x3, l_anon.[ID].10@PAGEOFF add x0, sp, #8 - mov w3, #1 + mov w4, #15 bl SYM(::add_method_inner, 0) Ltmp21: ldr x19, [sp, #8] @@ -420,20 +408,20 @@ Ltmp21: add sp, sp, #48 ret LBB6_15: -Lloh87: +Lloh83: adrp x0, l_anon.[ID].2@PAGE -Lloh88: +Lloh84: add x0, x0, l_anon.[ID].2@PAGEOFF bl SYM(core[CRATE_ID]::option::unwrap_failed, 0) LBB6_16: -Lloh89: - adrp x0, l_anon.[ID].12@PAGE -Lloh90: - add x0, x0, l_anon.[ID].12@PAGEOFF -Lloh91: - adrp x2, l_anon.[ID].14@PAGE -Lloh92: - add x2, x2, l_anon.[ID].14@PAGEOFF +Lloh85: + adrp x0, l_anon.[ID].11@PAGE +Lloh86: + add x0, x0, l_anon.[ID].11@PAGEOFF +Lloh87: + adrp x2, l_anon.[ID].13@PAGE +Lloh88: + add x2, x2, l_anon.[ID].13@PAGEOFF mov w1, #8 bl SYM(objc2[CRATE_ID]::__macros::define_class::checks::class_not_unique, 0) LBB6_17: @@ -457,19 +445,17 @@ Ltmp22: .loh AdrpAdd Lloh65, Lloh66 .loh AdrpAdd Lloh63, Lloh64 .loh AdrpLdr Lloh61, Lloh62 - .loh AdrpAdd Lloh73, Lloh74 .loh AdrpAdd Lloh71, Lloh72 .loh AdrpAdd Lloh69, Lloh70 .loh AdrpLdr Lloh67, Lloh68 + .loh AdrpAdd Lloh73, Lloh74 .loh AdrpAdd Lloh75, Lloh76 - .loh AdrpAdd Lloh77, Lloh78 - .loh AdrpAdd Lloh85, Lloh86 - .loh AdrpAdd Lloh83, Lloh84 .loh AdrpAdd Lloh81, Lloh82 - .loh AdrpLdr Lloh79, Lloh80 + .loh AdrpAdd Lloh79, Lloh80 + .loh AdrpLdr Lloh77, Lloh78 + .loh AdrpAdd Lloh83, Lloh84 .loh AdrpAdd Lloh87, Lloh88 - .loh AdrpAdd Lloh91, Lloh92 - .loh AdrpAdd Lloh89, Lloh90 + .loh AdrpAdd Lloh85, Lloh86 Lfunc_end1: .section __TEXT,__gcc_except_tab .p2align 2, 0x0 @@ -511,22 +497,22 @@ SYM(::method_retained, 0): sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh93: +Lloh89: adrp x8, ___REGISTER_CLASS_NoIvars@PAGE -Lloh94: +Lloh90: add x8, x8, ___REGISTER_CLASS_NoIvars@PAGEOFF ldapr x8, [x8] cbnz x8, LBB8_2 LBB8_1: -Lloh95: +Lloh91: adrp x8, ___CLASS_NoIvars@PAGE -Lloh96: +Lloh92: ldr x0, [x8, ___CLASS_NoIvars@PAGEOFF] -Lloh97: +Lloh93: adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE -Lloh98: +Lloh94: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] -Lloh99: +Lloh95: ldr x1, [x8] bl _objc_msgSend ldp x29, x30, [sp, #16] @@ -537,29 +523,29 @@ LBB8_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh100: +Lloh96: adrp x0, ___REGISTER_CLASS_NoIvars@PAGE -Lloh101: +Lloh97: add x0, x0, ___REGISTER_CLASS_NoIvars@PAGEOFF -Lloh102: +Lloh98: adrp x3, l_anon.[ID].0@PAGE -Lloh103: +Lloh99: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh104: - adrp x4, l_anon.[ID].14@PAGE -Lloh105: - add x4, x4, l_anon.[ID].14@PAGEOFF +Lloh100: + adrp x4, l_anon.[ID].13@PAGE +Lloh101: + add x4, x4, l_anon.[ID].13@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(::call, 0) b LBB8_1 - .loh AdrpAdd Lloh93, Lloh94 - .loh AdrpLdrGotLdr Lloh97, Lloh98, Lloh99 - .loh AdrpAdrp Lloh95, Lloh97 - .loh AdrpLdr Lloh95, Lloh96 - .loh AdrpAdd Lloh104, Lloh105 - .loh AdrpAdd Lloh102, Lloh103 + .loh AdrpAdd Lloh89, Lloh90 + .loh AdrpLdrGotLdr Lloh93, Lloh94, Lloh95 + .loh AdrpAdrp Lloh91, Lloh93 + .loh AdrpLdr Lloh91, Lloh92 .loh AdrpAdd Lloh100, Lloh101 + .loh AdrpAdd Lloh98, Lloh99 + .loh AdrpAdd Lloh96, Lloh97 .globl SYM(::method_retained_with_param, 0) .p2align 2 @@ -640,15 +626,15 @@ Lttbase1: .globl SYM(::get_class, 0) .p2align 2 SYM(::get_class, 0): -Lloh106: +Lloh102: adrp x8, ___REGISTER_CLASS_NoIvars@PAGE -Lloh107: +Lloh103: add x8, x8, ___REGISTER_CLASS_NoIvars@PAGEOFF ldapr x8, [x8] cbnz x8, LBB10_2 -Lloh108: +Lloh104: adrp x8, ___CLASS_NoIvars@PAGE -Lloh109: +Lloh105: ldr x0, [x8, ___CLASS_NoIvars@PAGEOFF] ret LBB10_2: @@ -659,34 +645,34 @@ LBB10_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh110: +Lloh106: adrp x0, ___REGISTER_CLASS_NoIvars@PAGE -Lloh111: +Lloh107: add x0, x0, ___REGISTER_CLASS_NoIvars@PAGEOFF -Lloh112: +Lloh108: adrp x3, l_anon.[ID].0@PAGE -Lloh113: +Lloh109: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh114: - adrp x4, l_anon.[ID].14@PAGE -Lloh115: - add x4, x4, l_anon.[ID].14@PAGEOFF +Lloh110: + adrp x4, l_anon.[ID].13@PAGE +Lloh111: + add x4, x4, l_anon.[ID].13@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(::call, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh116: +Lloh112: adrp x8, ___CLASS_NoIvars@PAGE -Lloh117: +Lloh113: ldr x0, [x8, ___CLASS_NoIvars@PAGEOFF] ret - .loh AdrpAdd Lloh106, Lloh107 - .loh AdrpLdr Lloh108, Lloh109 - .loh AdrpLdr Lloh116, Lloh117 - .loh AdrpAdd Lloh114, Lloh115 - .loh AdrpAdd Lloh112, Lloh113 + .loh AdrpAdd Lloh102, Lloh103 + .loh AdrpLdr Lloh104, Lloh105 + .loh AdrpLdr Lloh112, Lloh113 .loh AdrpAdd Lloh110, Lloh111 + .loh AdrpAdd Lloh108, Lloh109 + .loh AdrpAdd Lloh106, Lloh107 .globl SYM(::copy_with_zone, 0) .p2align 2 @@ -694,22 +680,22 @@ SYM(::copy_with_zone, 0): sub sp, sp, #32 stp x29, x30, [sp, #16] add x29, sp, #16 -Lloh118: +Lloh114: adrp x8, ___REGISTER_CLASS_NoIvars@PAGE -Lloh119: +Lloh115: add x8, x8, ___REGISTER_CLASS_NoIvars@PAGEOFF ldapr x8, [x8] cbnz x8, LBB11_2 LBB11_1: -Lloh120: +Lloh116: adrp x8, ___CLASS_NoIvars@PAGE -Lloh121: +Lloh117: ldr x0, [x8, ___CLASS_NoIvars@PAGEOFF] -Lloh122: +Lloh118: adrp x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGE -Lloh123: +Lloh119: ldr x8, [x8, L_OBJC_SELECTOR_REFERENCES_new@GOTPAGEOFF] -Lloh124: +Lloh120: ldr x1, [x8] bl _objc_msgSend ldp x29, x30, [sp, #16] @@ -720,42 +706,42 @@ LBB11_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh125: +Lloh121: adrp x0, ___REGISTER_CLASS_NoIvars@PAGE -Lloh126: +Lloh122: add x0, x0, ___REGISTER_CLASS_NoIvars@PAGEOFF -Lloh127: +Lloh123: adrp x3, l_anon.[ID].0@PAGE -Lloh128: +Lloh124: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh129: - adrp x4, l_anon.[ID].14@PAGE -Lloh130: - add x4, x4, l_anon.[ID].14@PAGEOFF +Lloh125: + adrp x4, l_anon.[ID].13@PAGE +Lloh126: + add x4, x4, l_anon.[ID].13@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(::call, 0) b LBB11_1 - .loh AdrpAdd Lloh118, Lloh119 - .loh AdrpLdrGotLdr Lloh122, Lloh123, Lloh124 - .loh AdrpAdrp Lloh120, Lloh122 - .loh AdrpLdr Lloh120, Lloh121 - .loh AdrpAdd Lloh129, Lloh130 - .loh AdrpAdd Lloh127, Lloh128 + .loh AdrpAdd Lloh114, Lloh115 + .loh AdrpLdrGotLdr Lloh118, Lloh119, Lloh120 + .loh AdrpAdrp Lloh116, Lloh118 + .loh AdrpLdr Lloh116, Lloh117 .loh AdrpAdd Lloh125, Lloh126 + .loh AdrpAdd Lloh123, Lloh124 + .loh AdrpAdd Lloh121, Lloh122 .globl SYM(::class, 0) .p2align 2 SYM(::class, 0): -Lloh131: +Lloh127: adrp x8, ___REGISTER_CLASS_NoIvars@PAGE -Lloh132: +Lloh128: add x8, x8, ___REGISTER_CLASS_NoIvars@PAGEOFF ldapr x8, [x8] cbnz x8, LBB12_2 -Lloh133: +Lloh129: adrp x8, ___CLASS_NoIvars@PAGE -Lloh134: +Lloh130: ldr x0, [x8, ___CLASS_NoIvars@PAGEOFF] ret LBB12_2: @@ -766,34 +752,34 @@ LBB12_2: strb w8, [sp, #7] add x8, sp, #7 str x8, [sp, #8] -Lloh135: +Lloh131: adrp x0, ___REGISTER_CLASS_NoIvars@PAGE -Lloh136: +Lloh132: add x0, x0, ___REGISTER_CLASS_NoIvars@PAGEOFF -Lloh137: +Lloh133: adrp x3, l_anon.[ID].0@PAGE -Lloh138: +Lloh134: add x3, x3, l_anon.[ID].0@PAGEOFF -Lloh139: - adrp x4, l_anon.[ID].14@PAGE -Lloh140: - add x4, x4, l_anon.[ID].14@PAGEOFF +Lloh135: + adrp x4, l_anon.[ID].13@PAGE +Lloh136: + add x4, x4, l_anon.[ID].13@PAGEOFF add x2, sp, #8 mov w1, #0 bl SYM(::call, 0) ldp x29, x30, [sp, #16] add sp, sp, #32 -Lloh141: +Lloh137: adrp x8, ___CLASS_NoIvars@PAGE -Lloh142: +Lloh138: ldr x0, [x8, ___CLASS_NoIvars@PAGEOFF] ret - .loh AdrpAdd Lloh131, Lloh132 - .loh AdrpLdr Lloh133, Lloh134 - .loh AdrpLdr Lloh141, Lloh142 - .loh AdrpAdd Lloh139, Lloh140 - .loh AdrpAdd Lloh137, Lloh138 + .loh AdrpAdd Lloh127, Lloh128 + .loh AdrpLdr Lloh129, Lloh130 + .loh AdrpLdr Lloh137, Lloh138 .loh AdrpAdd Lloh135, Lloh136 + .loh AdrpAdd Lloh133, Lloh134 + .loh AdrpAdd Lloh131, Lloh132 .section __TEXT,__objc_methname,cstring_literals .globl L_OBJC_METH_VAR_NAME_44ec46acb208c3d4 @@ -899,66 +885,44 @@ l_anon.[ID].2: .quad l_anon.[ID].1 .asciz "p\000\000\000\000\000\000\000\237\000\000\0002\000\000" - .section __TEXT,__const - .p2align 3, 0x0 + .section __TEXT,__cstring,cstring_literals l_anon.[ID].3: - .byte 23 - .space 39 + .asciz "#@:" - .p2align 3, 0x0 l_anon.[ID].4: - .byte 19 - .space 39 + .asciz "v@:" - .p2align 3, 0x0 l_anon.[ID].5: - .byte 18 - .space 39 + .asciz "B@:B" - .p2align 3, 0x0 l_anon.[ID].6: - .byte 21 - .space 39 + .asciz "@@:" - .section __TEXT,__literal8,8byte_literals l_anon.[ID].7: - .ascii "NSObject" + .asciz "@@:B" - .section __TEXT,__const + .section __TEXT,__literal8,8byte_literals l_anon.[ID].8: - .ascii "NSCopying" + .ascii "NSObject" + .section __TEXT,__const l_anon.[ID].9: - .ascii "_NSZone" + .ascii "NSCopying" - .section __DATA,__const - .p2align 3, 0x0 + .section __TEXT,__cstring,cstring_literals l_anon.[ID].10: - .byte 30 - .space 7 - .quad l_anon.[ID].9 - .asciz "\007\000\000\000\000\000\000" - .quad 8 - .space 8 + .asciz "@@:^{_NSZone=}" - .p2align 3, 0x0 l_anon.[ID].11: - .byte 27 - .space 7 - .quad l_anon.[ID].10 - .space 24 - - .section __TEXT,__cstring,cstring_literals -l_anon.[ID].12: .asciz "NoIvars" -l_anon.[ID].13: +l_anon.[ID].12: .asciz "crates/$DIR/lib.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].14: - .quad l_anon.[ID].13 +l_anon.[ID].13: + .quad l_anon.[ID].12 .asciz "=\000\000\000\000\000\000\000\r\000\000\000\001\000\000" .globl ___CLASS_NoIvars diff --git a/crates/test-assembly/crates/test_define_class_no_ivars/expected/apple-x86_64.s b/crates/test-assembly/crates/test_define_class_no_ivars/expected/apple-x86_64.s index 2f7019bf5..e02e7ce9b 100644 --- a/crates/test-assembly/crates/test_define_class_no_ivars/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_define_class_no_ivars/expected/apple-x86_64.s @@ -16,7 +16,7 @@ LBB0_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + ___REGISTER_CLASS_NoIvars] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].14] + lea r8, [rip + l_anon.[ID].13] lea rdx, [rbp - 16] xor esi, esi call SYM(::call, 0) @@ -135,7 +135,7 @@ LBB3_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + ___REGISTER_CLASS_NoIvars] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].14] + lea r8, [rip + l_anon.[ID].13] lea rdx, [rbp - 16] xor esi, esi call SYM(::call, 0) @@ -165,7 +165,7 @@ LBB4_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + ___REGISTER_CLASS_NoIvars] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].14] + lea r8, [rip + l_anon.[ID].13] lea rdx, [rbp - 16] xor esi, esi call SYM(::call, 0) @@ -192,7 +192,7 @@ Lfunc_begin1: jne LBB6_17 mov rax, qword ptr [rip + L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPCREL] mov rdi, qword ptr [rax] - lea rsi, [rip + L_anon.[ID].12] + lea rsi, [rip + L_anon.[ID].11] xor edx, edx call _objc_allocateClassPair test rax, rax @@ -200,51 +200,46 @@ Lfunc_begin1: mov qword ptr [rbp - 16], rax mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_a9fb958c74006297] Ltmp6: - lea r8, [rip + l_anon.[ID].3] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, &objc2[CRATE_ID]::runtime::anyclass::AnyClass, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)] + lea rcx, [rip + L_anon.[ID].3] lea rdi, [rbp - 16] - mov edx, 8 - xor ecx, ecx + mov r8d, 4 call SYM(::add_class_method_inner, 0) Ltmp7: mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_adfe2eb45443b755] Ltmp8: - lea r8, [rip + l_anon.[ID].4] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, (), objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, (), objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)] + lea rcx, [rip + L_anon.[ID].4] lea rdi, [rbp - 16] - mov edx, 8 - xor ecx, ecx + mov r8d, 4 call SYM(::add_method_inner, 0) Ltmp9: mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_71045e8f6bc4d4f9] Ltmp10: - lea rdx, [rip + l_anon.[ID].5] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, bool, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, bool, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)] + lea rcx, [rip + L_anon.[ID].5] lea rdi, [rbp - 16] - mov ecx, 1 - mov r8, rdx + mov r8d, 5 call SYM(::add_method_inner, 0) Ltmp11: mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_44ec46acb208c3d4] Ltmp12: - lea r8, [rip + l_anon.[ID].6] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars>, 0)] + lea rcx, [rip + L_anon.[ID].6] lea rdi, [rbp - 16] - mov edx, 8 - xor ecx, ecx + mov r8d, 4 call SYM(::add_method_inner, 0) Ltmp13: mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_d63b759d5c7ed4f0] Ltmp14: - lea rdx, [rip + l_anon.[ID].5] - lea r8, [rip + l_anon.[ID].6] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<6u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, bool>, 0)] + lea rcx, [rip + L_anon.[ID].7] lea rdi, [rbp - 16] - mov ecx, 1 + mov r8d, 5 call SYM(::add_method_inner, 0) Ltmp15: Ltmp16: - lea rdi, [rip + L_anon.[ID].7] + lea rdi, [rip + L_anon.[ID].8] mov esi, 8 call SYM(objc2[CRATE_ID]::top_level_traits::get_protocol, 0) Ltmp17: @@ -255,7 +250,7 @@ Ltmp17: call _class_addProtocol LBB6_10: Ltmp18: - lea rdi, [rip + l_anon.[ID].8] + lea rdi, [rip + l_anon.[ID].9] mov esi, 9 call SYM(objc2[CRATE_ID]::top_level_traits::get_protocol, 0) Ltmp19: @@ -267,11 +262,10 @@ Ltmp19: LBB6_13: mov rsi, qword ptr [rip + L_OBJC_SELECTOR_REFERENCES_996a3b5043cf563d] Ltmp20: - lea rdx, [rip + l_anon.[ID].11] - lea r8, [rip + l_anon.[ID].6] - lea r9, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<4u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, *const objc2[CRATE_ID]::runtime::nszone::NSZone>, 0)] + lea rdx, [rip + SYM(objc2[CRATE_ID]::__macros::define_class::thunk::_::thunk::<::class::{closure#0}::{closure#0}::__FnMarker, &test_define_class_no_ivars[CRATE_ID]::NoIvars, core[CRATE_ID]::option::Option>, objc2[CRATE_ID]::__macros::method_family::MethodFamily<4u8>, test_define_class_no_ivars[CRATE_ID]::NoIvars, *const objc2[CRATE_ID]::runtime::nszone::NSZone>, 0)] + lea rcx, [rip + L_anon.[ID].10] lea rdi, [rbp - 16] - mov ecx, 1 + mov r8d, 15 call SYM(::add_method_inner, 0) Ltmp21: mov rbx, qword ptr [rbp - 16] @@ -286,8 +280,8 @@ LBB6_17: lea rdi, [rip + l_anon.[ID].2] call SYM(core[CRATE_ID]::option::unwrap_failed, 0) LBB6_16: - lea rdi, [rip + L_anon.[ID].12] - lea rdx, [rip + l_anon.[ID].14] + lea rdi, [rip + L_anon.[ID].11] + lea rdx, [rip + l_anon.[ID].13] mov esi, 8 call SYM(objc2[CRATE_ID]::__macros::define_class::checks::class_not_unique, 0) LBB6_15: @@ -355,7 +349,7 @@ LBB8_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + ___REGISTER_CLASS_NoIvars] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].14] + lea r8, [rip + l_anon.[ID].13] lea rdx, [rbp - 16] xor esi, esi call SYM(::call, 0) @@ -457,7 +451,7 @@ LBB10_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + ___REGISTER_CLASS_NoIvars] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].14] + lea r8, [rip + l_anon.[ID].13] lea rdx, [rbp - 16] xor esi, esi call SYM(::call, 0) @@ -489,7 +483,7 @@ LBB11_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + ___REGISTER_CLASS_NoIvars] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].14] + lea r8, [rip + l_anon.[ID].13] lea rdx, [rbp - 16] xor esi, esi call SYM(::call, 0) @@ -512,7 +506,7 @@ LBB12_1: mov qword ptr [rbp - 16], rax lea rdi, [rip + ___REGISTER_CLASS_NoIvars] lea rcx, [rip + l_anon.[ID].0] - lea r8, [rip + l_anon.[ID].14] + lea r8, [rip + l_anon.[ID].13] lea rdx, [rbp - 16] xor esi, esi call SYM(::call, 0) @@ -625,66 +619,44 @@ l_anon.[ID].2: .quad L_anon.[ID].1 .asciz "p\000\000\000\000\000\000\000\237\000\000\0002\000\000" - .section __TEXT,__const - .p2align 3, 0x0 -l_anon.[ID].3: - .byte 23 - .space 39 + .section __TEXT,__cstring,cstring_literals +L_anon.[ID].3: + .asciz "#@:" - .p2align 3, 0x0 -l_anon.[ID].4: - .byte 19 - .space 39 +L_anon.[ID].4: + .asciz "v@:" - .p2align 3, 0x0 -l_anon.[ID].5: - .space 1 - .space 39 +L_anon.[ID].5: + .asciz "c@:c" - .p2align 3, 0x0 -l_anon.[ID].6: - .byte 21 - .space 39 +L_anon.[ID].6: + .asciz "@@:" - .section __TEXT,__literal8,8byte_literals L_anon.[ID].7: + .asciz "@@:c" + + .section __TEXT,__literal8,8byte_literals +L_anon.[ID].8: .ascii "NSObject" .section __TEXT,__const -l_anon.[ID].8: - .ascii "NSCopying" - l_anon.[ID].9: - .ascii "_NSZone" - - .section __DATA,__const - .p2align 3, 0x0 -l_anon.[ID].10: - .byte 30 - .space 7 - .quad l_anon.[ID].9 - .asciz "\007\000\000\000\000\000\000" - .quad 8 - .space 8 - - .p2align 3, 0x0 -l_anon.[ID].11: - .byte 27 - .space 7 - .quad l_anon.[ID].10 - .space 24 + .ascii "NSCopying" .section __TEXT,__cstring,cstring_literals -L_anon.[ID].12: +L_anon.[ID].10: + .asciz "@@:^{_NSZone=}" + +L_anon.[ID].11: .asciz "NoIvars" -L_anon.[ID].13: +L_anon.[ID].12: .asciz "crates/$DIR/lib.rs" .section __DATA,__const .p2align 3, 0x0 -l_anon.[ID].14: - .quad L_anon.[ID].13 +l_anon.[ID].13: + .quad L_anon.[ID].12 .asciz "=\000\000\000\000\000\000\000\r\000\000\000\001\000\000" .globl ___CLASS_NoIvars diff --git a/crates/test-ui/ui/define_class_invalid_receiver.stderr b/crates/test-ui/ui/define_class_invalid_receiver.stderr index 7508825be..d0536feb1 100644 --- a/crates/test-ui/ui/define_class_invalid_receiver.stderr +++ b/crates/test-ui/ui/define_class_invalid_receiver.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `Box: MessageReceiver` is not satisfied *mut T NonNull = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics, (), objc2::__macros::KindDefined>` - = note: required for `fn(Box)` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestBox>` + = note: required for `fn(Box)` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestBox>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -40,7 +40,7 @@ error[E0277]: the trait bound `Retained: MessageReceiver` is n *mut T NonNull = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics, (), objc2::__macros::KindDefined>` - = note: required for `fn(Retained)` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestRetainedSelf>` + = note: required for `fn(Retained)` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestRetainedSelf>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -74,7 +74,7 @@ help: the trait `MessageReceiver` is not implemented for `TestSelf` *mut T NonNull = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics` - = note: required for `fn(TestSelf)` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestSelf>` + = note: required for `fn(TestSelf)` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestSelf>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -99,7 +99,7 @@ error[E0277]: the trait bound `Box: MessageReceiver` is n *mut T NonNull = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics, Retained, objc2::__macros::KindDefined>` - = note: required for `fn(Box) -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestBoxReturnRetained>` + = note: required for `fn(Box) -> Retained` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestBoxReturnRetained>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -124,7 +124,7 @@ error[E0277]: the trait bound `Retained: MessageRece *mut T NonNull = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics, Retained, objc2::__macros::KindDefined>` - = note: required for `fn(Retained) -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestRetainedReturnRetained>` + = note: required for `fn(Retained) -> Retained` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, TestRetainedReturnRetained>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -149,7 +149,7 @@ error[E0277]: the trait bound `Allocated: MessageReceiver` is not *mut T NonNull = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics, Retained, objc2::__macros::KindDefined>` - = note: required for `fn(Allocated) -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, NormalNotInit>` + = note: required for `fn(Allocated) -> Retained` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, NormalNotInit>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -180,7 +180,7 @@ error[E0277]: the trait bound `Retained: Encode` is not satisfied = note: required for `Retained` to implement `EncodeReturn` = note: required for `Retained` to implement `objc2::__macros::ConvertReturn>` = note: required for `objc2::__macros::MethodFamily<3>` to implement `objc2::__macros::RetainSemantics<&'__function InitNotAlloc, Retained, objc2::__macros::KindDefined>` - = note: required for `fn(&'__function InitNotAlloc) -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<3>, objc2::__macros::MethodKind, InitNotAlloc>` + = note: required for `fn(&'__function InitNotAlloc) -> Retained` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<3>, objc2::__macros::MethodKind, InitNotAlloc>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -270,7 +270,7 @@ error[E0271]: type mismatch resolving `::add_method` --> $WORKSPACE/crates/objc2/src/__macros/define_class/checks.rs | - | pub unsafe fn add_method(&mut self, sel: Sel, func: F) + | pub unsafe fn add_method(&mut self, sel: Sel, func: F, encoding: &CStr) | ---------- required by a bound in this associated function | where | F: MethodImplementation, @@ -293,7 +293,7 @@ error[E0271]: type mismatch resolving `::add_method` --> $WORKSPACE/crates/objc2/src/__macros/define_class/checks.rs | - | pub unsafe fn add_method(&mut self, sel: Sel, func: F) + | pub unsafe fn add_method(&mut self, sel: Sel, func: F, encoding: &CStr) | ---------- required by a bound in this associated function | where | F: MethodImplementation, diff --git a/crates/test-ui/ui/define_class_invalid_receiver_retain_semantics.stderr b/crates/test-ui/ui/define_class_invalid_receiver_retain_semantics.stderr index e35725bee..84ac1dcab 100644 --- a/crates/test-ui/ui/define_class_invalid_receiver_retain_semantics.stderr +++ b/crates/test-ui/ui/define_class_invalid_receiver_retain_semantics.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `objc2::__macros::MethodFamily<6>: objc2::__macros `objc2::__macros::MethodFamily<3>` implements `objc2::__macros::RetainSemantics, Retained, Kind>` `objc2::__macros::MethodFamily<3>` implements `objc2::__macros::RetainSemantics, Option>, Kind>` `objc2::__macros::MethodFamily<3>` implements `objc2::__macros::RetainSemantics, Retained, Kind>` - = note: required for `fn(&'__function Retained)` to implement `objc2::__macros::define_class::thunk::FnToExternFn<__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` + = note: required for `fn(&'__function Retained)` to implement `objc2::__macros::FnToExternFn<__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -40,5 +40,5 @@ error[E0277]: the trait bound `objc2::__macros::MethodFamily<6>: objc2::__macros `objc2::__macros::MethodFamily<3>` implements `objc2::__macros::RetainSemantics, Retained, Kind>` `objc2::__macros::MethodFamily<3>` implements `objc2::__macros::RetainSemantics, Option>, Kind>` `objc2::__macros::MethodFamily<3>` implements `objc2::__macros::RetainSemantics, Retained, Kind>` - = note: required for `fn(&Retained)` to implement `objc2::__macros::define_class::thunk::FnToExternFn<__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` + = note: required for `fn(&Retained)` to implement `objc2::__macros::FnToExternFn<__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` = note: this error originates in the macro `$crate::__declare_class_register_thunk` which comes from the expansion of the macro `define_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/define_class_invalid_type.stderr b/crates/test-ui/ui/define_class_invalid_type.stderr index 02ad8265c..71eba643a 100644 --- a/crates/test-ui/ui/define_class_invalid_type.stderr +++ b/crates/test-ui/ui/define_class_invalid_type.stderr @@ -21,7 +21,7 @@ error[E0277]: the trait bound `Vec<()>: Encode` is not satisfied = note: required for `Vec<()>` to implement `EncodeReturn` = note: required for `Vec<()>` to implement `objc2::__macros::ConvertReturn>` = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics<&AnyClass, Vec<()>, objc2::__macros::KindDefined>` - = note: required for `fn() -> Vec<()>` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::ClassFnKind<&AnyClass>, CustomObject>` + = note: required for `fn() -> Vec<()>` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::ClassFnKind<&AnyClass>, CustomObject>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -51,7 +51,7 @@ error[E0277]: the trait bound `Box: Encode` is not satisfied and $N others = note: required for `Box` to implement `EncodeArgument` = note: required for `Box` to implement `objc2::__macros::ConvertArgument` - = note: required for `fn(&'__function CustomObject, Box)` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` + = note: required for `fn(&'__function CustomObject, Box)` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -90,7 +90,7 @@ help: the trait `Encode` is not implemented for `CustomObject` and $N others = note: required for `CustomObject` to implement `EncodeArgument` = note: required for `CustomObject` to implement `objc2::__macros::ConvertArgument` - = note: required for `fn(&'__function CustomObject, CustomObject)` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` + = note: required for `fn(&'__function CustomObject, CustomObject)` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | diff --git a/crates/test-ui/ui/define_class_invalid_type2.stderr b/crates/test-ui/ui/define_class_invalid_type2.stderr index b49939235..c20a7d45a 100644 --- a/crates/test-ui/ui/define_class_invalid_type2.stderr +++ b/crates/test-ui/ui/define_class_invalid_type2.stderr @@ -15,7 +15,7 @@ error[E0277]: the trait bound `Allocated: MessageReceiver` is not *mut T NonNull = note: required for `objc2::__macros::MethodFamily<3>` to implement `objc2::__macros::RetainSemantics, Retained, objc2::__macros::KindDefined>` - = note: required for `fn(Allocated) -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<__FnMarker, objc2::__macros::MethodFamily<3>, objc2::__macros::MethodKind, CustomObject>` + = note: required for `fn(Allocated) -> Retained` to implement `objc2::__macros::FnToExternFn<__FnMarker, objc2::__macros::MethodFamily<3>, objc2::__macros::MethodKind, CustomObject>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -46,7 +46,7 @@ error[E0277]: the trait bound `Retained: Encode` is not satisfied = note: required for `Retained` to implement `EncodeReturn` = note: required for `Retained` to implement `objc2::__macros::ConvertReturn>` = note: required for `objc2::__macros::MethodFamily<3>` to implement `objc2::__macros::RetainSemantics, Retained, objc2::__macros::KindDefined>` - = note: required for `fn(Allocated) -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<__FnMarker, objc2::__macros::MethodFamily<3>, objc2::__macros::MethodKind, CustomObject>` + = note: required for `fn(Allocated) -> Retained` to implement `objc2::__macros::FnToExternFn<__FnMarker, objc2::__macros::MethodFamily<3>, objc2::__macros::MethodKind, CustomObject>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | diff --git a/crates/test-ui/ui/define_class_invalid_type3.stderr b/crates/test-ui/ui/define_class_invalid_type3.stderr index 13af0ce54..86d0e758d 100644 --- a/crates/test-ui/ui/define_class_invalid_type3.stderr +++ b/crates/test-ui/ui/define_class_invalid_type3.stderr @@ -21,7 +21,7 @@ error[E0277]: the trait bound `Retained: Encode` is not satisfied = note: required for `Retained` to implement `EncodeReturn` = note: required for `Retained` to implement `objc2::__macros::ConvertReturn>` = note: required for `objc2::__macros::MethodFamily<8>` to implement `objc2::__macros::RetainSemantics<&AnyClass, Retained, objc2::__macros::KindDefined>` - = note: required for `fn() -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<8>, objc2::__macros::ClassFnKind<&AnyClass>, BadSelectors>` + = note: required for `fn() -> Retained` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<8>, objc2::__macros::ClassFnKind<&AnyClass>, BadSelectors>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -52,7 +52,7 @@ error[E0277]: the trait bound `Retained: Encode` is not satisfied = note: required for `Retained` to implement `EncodeReturn` = note: required for `Retained` to implement `objc2::__macros::ConvertReturn>` = note: required for `objc2::__macros::MethodFamily<9>` to implement `objc2::__macros::RetainSemantics<&AnyClass, Retained, objc2::__macros::KindDefined>` - = note: required for `fn() -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<9>, objc2::__macros::ClassFnKind<&AnyClass>, BadSelectors>` + = note: required for `fn() -> Retained` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<9>, objc2::__macros::ClassFnKind<&AnyClass>, BadSelectors>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -83,7 +83,7 @@ error[E0277]: the trait bound `Retained: Encode` is not satisfied = note: required for `Retained` to implement `EncodeReturn` = note: required for `Retained` to implement `objc2::__macros::ConvertReturn>` = note: required for `objc2::__macros::MethodFamily<10>` to implement `objc2::__macros::RetainSemantics<&AnyClass, Retained, objc2::__macros::KindDefined>` - = note: required for `fn() -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<10>, objc2::__macros::ClassFnKind<&AnyClass>, BadSelectors>` + = note: required for `fn() -> Retained` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<10>, objc2::__macros::ClassFnKind<&AnyClass>, BadSelectors>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | diff --git a/crates/test-ui/ui/define_class_mut_self_not_mutable.stderr b/crates/test-ui/ui/define_class_mut_self_not_mutable.stderr index 9bca3714f..a1f2d3410 100644 --- a/crates/test-ui/ui/define_class_mut_self_not_mutable.stderr +++ b/crates/test-ui/ui/define_class_mut_self_not_mutable.stderr @@ -42,7 +42,7 @@ error[E0277]: the trait bound `&'__function mut CustomObject: MessageReceiver` i NonNull = note: `MessageReceiver` is implemented for `&'__function CustomObject`, but not for `&'__function mut CustomObject` = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics<&'__function mut CustomObject, (), objc2::__macros::KindDefined>` - = note: required for `fn(&'__function mut CustomObject)` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` + = note: required for `fn(&'__function mut CustomObject)` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs | @@ -68,7 +68,7 @@ error[E0277]: the trait bound `&'__function mut CustomObject: MessageReceiver` i NonNull = note: `MessageReceiver` is implemented for `&'__function CustomObject`, but not for `&'__function mut CustomObject` = note: required for `objc2::__macros::MethodFamily<6>` to implement `objc2::__macros::RetainSemantics<&'__function mut CustomObject, Retained, objc2::__macros::KindDefined>` - = note: required for `fn(&'__function mut CustomObject) -> Retained` to implement `objc2::__macros::define_class::thunk::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` + = note: required for `fn(&'__function mut CustomObject) -> Retained` to implement `objc2::__macros::FnToExternFn<_::::class::{closure#0}::{closure#0}::__FnMarker, objc2::__macros::MethodFamily<6>, objc2::__macros::MethodKind, CustomObject>` note: required by a bound in `objc2::__macros::ConvertDefinedFn::Func` --> $WORKSPACE/crates/objc2/src/__macros/define_class/thunk.rs |