From 7678c56c863e980cb9227158cb3857c99fcf5da7 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Fri, 6 Sep 2024 21:12:07 +0200 Subject: [PATCH] Completely remove the ability to create mutable objects The ability to specify whether an object is thread-safe or not has been kept, `ClassType::Mutability` has been renamed to `ThreadKind` and used in that way instead. It can be omitted from `extern_class!` most of the time, since we can make it default to that of the superclass. Finally fixes https://github.com/madsmtm/objc2/issues/563 --- README.md | 2 +- crates/block2/src/lib.rs | 1 - crates/header-translator/README.md | 2 +- crates/header-translator/src/config.rs | 8 +- crates/header-translator/src/method.rs | 2 +- crates/header-translator/src/stmt.rs | 8 +- crates/objc2/CHANGELOG.md | 64 +++- crates/objc2/Cargo.toml | 1 + crates/objc2/examples/class_with_lifetime.rs | 3 +- crates/objc2/src/__framework_prelude.rs | 5 +- crates/objc2/src/__macro_helpers/class.rs | 107 ++++++ .../src/__macro_helpers/declare_class.rs | 32 -- .../src/__macro_helpers/declared_ivars.rs | 14 +- crates/objc2/src/__macro_helpers/mod.rs | 6 +- crates/objc2/src/__macro_helpers/msg_send.rs | 5 +- .../objc2/src/__macro_helpers/msg_send_id.rs | 2 +- crates/objc2/src/lib.rs | 9 +- crates/objc2/src/macros/declare_class.rs | 31 +- crates/objc2/src/macros/extern_class.rs | 90 +++-- crates/objc2/src/macros/extern_methods.rs | 7 +- crates/objc2/src/macros/mod.rs | 3 +- crates/objc2/src/main_thread_marker.rs | 20 +- crates/objc2/src/mutability.rs | 241 -------------- crates/objc2/src/rc/id.rs | 16 +- crates/objc2/src/rc/id_traits.rs | 2 - crates/objc2/src/rc/test_object.rs | 2 - crates/objc2/src/runtime/declare.rs | 4 +- crates/objc2/src/runtime/nsobject.rs | 18 +- crates/objc2/src/runtime/nsproxy.rs | 5 +- crates/objc2/src/runtime/protocol_object.rs | 2 - crates/objc2/src/test_utils.rs | 6 +- crates/objc2/src/top_level_traits.rs | 307 +++++++++++++----- crates/objc2/src/topics/kvo.md | 4 +- crates/objc2/src/topics/layered_safety.md | 3 +- crates/objc2/src/topics/mvc.md | 6 +- crates/objc2/tests/declare_class.rs | 8 - crates/objc2/tests/declare_class_self.rs | 4 +- crates/objc2/tests/macros_mainthreadmarker.rs | 4 +- crates/objc2/tests/no_prelude.rs | 2 - crates/objc2/tests/track_caller.rs | 3 +- crates/objc2/tests/use_macros.rs | 2 - .../expected/apple-aarch64.s | 148 ++++----- .../expected/apple-x86_64.s | 132 ++++---- .../crates/test_declare_class/lib.rs | 5 +- .../fuzz_targets/collection_interior_mut.rs | 3 +- .../ui/declare_class_classtype_imported.rs | 3 +- ...clare_class_delegate_not_mainthreadonly.rs | 9 +- ...e_class_delegate_not_mainthreadonly.stderr | 12 +- .../ui/declare_class_invalid_receiver.rs | 3 +- .../ui/declare_class_invalid_syntax.rs | 15 +- .../ui/declare_class_invalid_syntax.stderr | 14 +- .../test-ui/ui/declare_class_invalid_type.rs | 3 +- .../test-ui/ui/declare_class_invalid_type2.rs | 3 +- .../ui/declare_class_mut_self_not_mutable.rs | 3 +- .../test-ui/ui/extern_class_feature_flag.rs | 4 +- crates/test-ui/ui/extern_class_not_zst.rs | 3 +- crates/test-ui/ui/extern_class_root.rs | 4 +- crates/test-ui/ui/extern_class_root.stderr | 8 + .../ui/extern_class_subclass_object.rs | 4 +- .../ui/extern_class_subclass_object.stderr | 8 + .../ui/extern_class_thread_kind_invalid.rs | 13 + .../extern_class_thread_kind_invalid.stderr | 44 +++ ...extern_class_thread_kind_main_send_sync.rs | 26 ++ ...rn_class_thread_kind_main_send_sync.stderr | 37 +++ .../extern_class_thread_kind_main_to_any.rs | 22 ++ ...xtern_class_thread_kind_main_to_any.stderr | 17 + .../ui/extern_class_wrong_mutability.rs | 22 -- .../ui/extern_class_wrong_mutability.stderr | 23 -- .../test-ui/ui/extern_methods_bad_selector.rs | 3 +- .../test-ui/ui/extern_methods_feature_flag.rs | 3 +- .../ui/extern_methods_feature_flag.stderr | 10 +- .../ui/extern_methods_invalid_receiver.rs | 3 +- .../test-ui/ui/extern_methods_invalid_type.rs | 3 +- .../ui/extern_methods_missing_method.rs | 3 +- .../ui/extern_methods_not_allowed_mutable.rs | 3 +- .../ui/extern_methods_selector_twice.rs | 3 +- crates/test-ui/ui/extern_methods_variadic.rs | 3 +- .../ui/extern_methods_wrong_arguments.rs | 3 +- .../extern_methods_wrong_arguments_error.rs | 3 +- .../ui/implement_protocol_missing_super.rs | 4 +- .../ui/main_thread_only_not_allocable.rs | 6 +- .../ui/main_thread_only_not_allocable.stderr | 33 +- .../ui/mainthreadmarker_from_nsobject.stderr | 10 +- .../ui/msg_send_id_invalid_error.stderr | 12 +- .../ui/mutability_traits_unimplementable.rs | 19 -- .../mutability_traits_unimplementable.stderr | 9 - .../ui/mutability_traits_unimplementable2.rs | 8 - .../mutability_traits_unimplementable2.stderr | 20 -- .../ui/ns_copying_without_copy_helper.rs | 3 +- .../ui/thread_kind_traits_unimplementable.rs | 33 ++ .../thread_kind_traits_unimplementable.stderr | 39 +++ .../ui/thread_kind_traits_unimplementable2.rs | 10 + ...thread_kind_traits_unimplementable2.stderr | 39 +++ crates/test-ui/ui/wrong_optional.rs | 5 +- .../tests/src/test_declare_class_protocol.rs | 8 - .../src/test_foundation_retain_semantics.rs | 2 - crates/tests/src/test_object.rs | 6 +- crates/tests/src/test_simd_return.rs | 3 +- .../objc2-app-kit/examples/delegate.rs | 9 +- .../objc2-authentication-services/src/lib.rs | 8 +- .../examples/speech_synthesis.rs | 5 +- .../objc2-foundation/src/array.rs | 2 +- .../objc2-foundation/src/attributed_string.rs | 2 +- .../objc2-foundation/src/copying.rs | 6 +- framework-crates/objc2-foundation/src/data.rs | 2 +- .../objc2-foundation/src/dictionary.rs | 2 +- .../objc2-foundation/src/error.rs | 2 +- .../objc2-foundation/src/exception.rs | 2 +- framework-crates/objc2-foundation/src/set.rs | 2 +- .../objc2-foundation/src/string.rs | 2 +- .../objc2-foundation/src/tests/auto_traits.rs | 3 +- .../src/tests/mutable_array.rs | 2 +- framework-crates/objc2-foundation/src/uuid.rs | 2 +- .../objc2-foundation/src/value.rs | 2 +- .../objc2-foundation/translation-config.toml | 8 +- .../objc2-metal/examples/triangle.rs | 17 +- .../objc2-web-kit/examples/browser.rs | 27 +- generated | 2 +- 118 files changed, 1089 insertions(+), 976 deletions(-) create mode 100644 crates/objc2/src/__macro_helpers/class.rs delete mode 100644 crates/objc2/src/mutability.rs create mode 100644 crates/test-ui/ui/extern_class_thread_kind_invalid.rs create mode 100644 crates/test-ui/ui/extern_class_thread_kind_invalid.stderr create mode 100644 crates/test-ui/ui/extern_class_thread_kind_main_send_sync.rs create mode 100644 crates/test-ui/ui/extern_class_thread_kind_main_send_sync.stderr create mode 100644 crates/test-ui/ui/extern_class_thread_kind_main_to_any.rs create mode 100644 crates/test-ui/ui/extern_class_thread_kind_main_to_any.stderr delete mode 100644 crates/test-ui/ui/extern_class_wrong_mutability.rs delete mode 100644 crates/test-ui/ui/extern_class_wrong_mutability.stderr delete mode 100644 crates/test-ui/ui/mutability_traits_unimplementable.rs delete mode 100644 crates/test-ui/ui/mutability_traits_unimplementable.stderr delete mode 100644 crates/test-ui/ui/mutability_traits_unimplementable2.rs delete mode 100644 crates/test-ui/ui/mutability_traits_unimplementable2.stderr create mode 100644 crates/test-ui/ui/thread_kind_traits_unimplementable.rs create mode 100644 crates/test-ui/ui/thread_kind_traits_unimplementable.stderr create mode 100644 crates/test-ui/ui/thread_kind_traits_unimplementable2.rs create mode 100644 crates/test-ui/ui/thread_kind_traits_unimplementable2.stderr diff --git a/README.md b/README.md index 217f225b8..b7bfb1d37 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ However, that just pushes the burden onto you, the user, and then we're not much better off! As such, we'll try to be as safe and idiomatic as possible; using references -instead of pointers to represent objects and their mutability, `Option` +instead of pointers to represent objects and their (interior) mutability, `Option` instead of `null`, doing memory management automatically instead of manually, and so on (see again [these notes on "Layered Safety"][layered-safety]). These abstractions should ideally be zero-cost, but this is of course a balancing diff --git a/crates/block2/src/lib.rs b/crates/block2/src/lib.rs index cd4d44f39..a208c2617 100644 --- a/crates/block2/src/lib.rs +++ b/crates/block2/src/lib.rs @@ -69,7 +69,6 @@ //! # //! # unsafe impl ClassType for MyClass { //! # type Super = objc2::runtime::NSObject; -//! # type Mutability = objc2::mutability::InteriorMutable; //! # const NAME: &'static str = "NSObject"; //! # } //! # ); diff --git a/crates/header-translator/README.md b/crates/header-translator/README.md index 625141450..bba6c8a51 100644 --- a/crates/header-translator/README.md +++ b/crates/header-translator/README.md @@ -65,7 +65,7 @@ Feel free to open a half-finished PR if you need assistance. The `translation-config.toml` file describes various tweaks that we need to do because our header translation is incomplete in some areas. -However, even if our header translation was perfect, we still need a way to enrich the generated data, since C headers have no way to describe which methods are safe, or mutable, and which are not! +However, even if our header translation was perfect, we still need a way to enrich the generated data, since C headers have no way to describe which methods are safe and which are not! ### What is required for a method to be safe? diff --git a/crates/header-translator/src/config.rs b/crates/header-translator/src/config.rs index 3df4d494a..5b456fb00 100644 --- a/crates/header-translator/src/config.rs +++ b/crates/header-translator/src/config.rs @@ -335,13 +335,13 @@ impl<'de> Deserialize<'de> for Counterpart { )) } - struct MutabilityVisitor; + struct CounterpartVisitor; - impl<'de> de::Visitor<'de> for MutabilityVisitor { + impl<'de> de::Visitor<'de> for CounterpartVisitor { type Value = Counterpart; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("mutability") + formatter.write_str("counterpart") } fn visit_str(self, value: &str) -> Result @@ -370,6 +370,6 @@ impl<'de> Deserialize<'de> for Counterpart { } } - deserializer.deserialize_str(MutabilityVisitor) + deserializer.deserialize_str(CounterpartVisitor) } } diff --git a/crates/header-translator/src/method.rs b/crates/header-translator/src/method.rs index beb6c4b24..d77820013 100644 --- a/crates/header-translator/src/method.rs +++ b/crates/header-translator/src/method.rs @@ -302,7 +302,7 @@ fn mainthreadonly_override<'a>( } if any_argument_provides_mainthreadmarker { - // MainThreadMarker can be retrieved via. `IsMainThreadOnly::mtm` + // MainThreadMarker can be retrieved via. `MainThreadOnly::mtm` // inside these methods, and hence passing it is redundant. false } else if result_type_requires_mainthreadmarker { diff --git a/crates/header-translator/src/stmt.rs b/crates/header-translator/src/stmt.rs index 040fb9af8..cb58061ce 100644 --- a/crates/header-translator/src/stmt.rs +++ b/crates/header-translator/src/stmt.rs @@ -702,7 +702,7 @@ impl Stmt { superclasses, designated_initializers, derives: data.map(|data| data.derives.clone()).unwrap_or_default(), - main_thread_only: thread_safety.inferred_mainthreadonly(), + main_thread_only: thread_safety.explicit_mainthreadonly(), skipped: data.map(|data| data.definition_skipped).unwrap_or_default(), // Ignore sendability on superclasses; since it's an auto // trait, it's propagated to subclasses anyhow! @@ -1724,9 +1724,7 @@ impl Stmt { GenericTyHelper(superclass_generics), )?; if *main_thread_only { - writeln!(f, " type Mutability = MainThreadOnly;")?; - } else { - writeln!(f, " type Mutability = InteriorMutable;")?; + writeln!(f, " type ThreadKind = dyn MainThreadOnly;")?; } if !generics.is_empty() { writeln!(f)?; @@ -2054,7 +2052,7 @@ impl Stmt { } else { write!(f, "+ ")?; } - write!(f, "IsMainThreadOnly")?; + write!(f, "MainThreadOnly")?; } writeln!(f, " {{")?; diff --git a/crates/objc2/CHANGELOG.md b/crates/objc2/CHANGELOG.md index ffd4face3..987e5ef98 100644 --- a/crates/objc2/CHANGELOG.md +++ b/crates/objc2/CHANGELOG.md @@ -17,6 +17,62 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Added `IsMainThreadOnly::mtm`. ### Changed +* **BREAKING**: Changed how you specify a class to only be available on the + main thread. It is now automatically inferred, and you only need to + overwrite it if your class is doing something different than its superclass. + + ```rust + // Before + declare_class!( + struct MyObject; + + unsafe impl ClassType for MyObject { + type Super = NSObject; + type Mutability = InteriorMutable; + const NAME: &'static str = "MyObject"; + } + + impl DeclaredClass for MyObject { + type Ivars = ...; + } + + // ... + ); + + // After + declare_class!( + struct MyObject; + + unsafe impl ClassType for MyObject { + type Super = NSObject; + // No need to specify mutability any more + // + // But if you need it (e.g. when implementing delegates), you can add: + // type ThreadKind = dyn MainThreadOnly; + const NAME: &'static str = "MyObject"; + } + + impl DeclaredClass for MyObject { + type Ivars = ...; + } + + // ... + ); + ``` +* **BREAKING**: Moved the common `retain` and `alloc` methods from `ClassType` + to `Message` and `AllocAnyThread`/`MainThreadOnly`, respectively. + + ```rust + // Before + use objc2::ClassType; + let my_obj = MyObject::init(MyObject::alloc()); + let retained = my_obj.retain(); + + // After + use objc2::{Message, AllocAnyThread}; // Need different trait imports + let my_obj = MyObject::init(MyObject::alloc()); + let retained = my_obj.retain(); + ``` * Print backtrace when catching exceptions with the `"catch-all"` feature. * Changed the return value of `ClassBuilder::add_protocol` to indicate whether the protocol was already present on the class or not. @@ -54,14 +110,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). `objc`). * **BREAKING**: Removed `AsMut`, `BorrowMut` and `DerefMut` implementations in `extern_class!` and `declare_class!`. -* **BREAKING**: Removed `mutability` options `Immutable`, `Mutable`, - `ImmutableWithMutableSubclass`, `MutableWithImmutableSuperclass`, - `InteriorMutableWithSubclass` and `InteriorMutableWithSuperclass`, along - with the related `IsAllowedMutable`, `CounterpartOrSelf`, `IsIdCloneable`, - `IsRetainable` and `IsMutable` traits. +* **BREAKING**: Removed the `mutability` module, and everything within. + Classes now always use interior mutability. * **BREAKING**: Removed `DerefMut` implementation for `Retained` when the `Retained` was mutable. -* **BREAKING**: Moved `retain` from `ClassType` to `Message`. ### Fixed * Remove an incorrect assertion when adding protocols to classes in an unexpected diff --git a/crates/objc2/Cargo.toml b/crates/objc2/Cargo.toml index a2d9141b5..12e5f1b38 100644 --- a/crates/objc2/Cargo.toml +++ b/crates/objc2/Cargo.toml @@ -142,6 +142,7 @@ memoffset = "0.9.0" block2 = { path = "../block2", default-features = false } objc2-foundation = { path = "../../framework-crates/objc2-foundation", default-features = false, features = [ "NSDictionary", + "NSGeometry", "NSKeyValueObserving", "NSObject", "NSString", diff --git a/crates/objc2/examples/class_with_lifetime.rs b/crates/objc2/examples/class_with_lifetime.rs index 53fae4618..f38807f9a 100644 --- a/crates/objc2/examples/class_with_lifetime.rs +++ b/crates/objc2/examples/class_with_lifetime.rs @@ -6,7 +6,6 @@ use std::marker::PhantomData; use std::sync::Once; use objc2::msg_send_id; -use objc2::mutability::InteriorMutable; use objc2::rc::Retained; use objc2::runtime::{AnyClass, ClassBuilder, NSObject}; use objc2::{ClassType, Encoding, Message, RefEncode}; @@ -60,7 +59,7 @@ impl<'a> MyObject<'a> { unsafe impl<'a> ClassType for MyObject<'a> { type Super = NSObject; - type Mutability = InteriorMutable; + type ThreadKind = ::ThreadKind; const NAME: &'static str = "MyObject"; fn class() -> &'static AnyClass { diff --git a/crates/objc2/src/__framework_prelude.rs b/crates/objc2/src/__framework_prelude.rs index e8cd9f8c8..bcebe9160 100644 --- a/crates/objc2/src/__framework_prelude.rs +++ b/crates/objc2/src/__framework_prelude.rs @@ -13,14 +13,13 @@ pub use std::os::raw::{ pub use crate::encode::{Encode, Encoding, RefEncode}; pub use crate::ffi::{NSInteger, NSIntegerMax, NSUInteger, NSUIntegerMax}; -pub use crate::mutability::{InteriorMutable, IsMainThreadOnly, MainThreadOnly}; pub use crate::rc::{Allocated, DefaultId, DefaultRetained, Id, Retained}; pub use crate::runtime::{ AnyClass, AnyObject, Bool, NSObject, NSObjectProtocol, ProtocolObject, Sel, }; pub use crate::{ - __inner_extern_class, extern_category, extern_class, extern_methods, extern_protocol, - ClassType, MainThreadMarker, Message, ProtocolType, + MainThreadOnly, __inner_extern_class, extern_category, extern_class, extern_methods, + extern_protocol, ClassType, MainThreadMarker, Message, ProtocolType, }; // TODO diff --git a/crates/objc2/src/__macro_helpers/class.rs b/crates/objc2/src/__macro_helpers/class.rs new file mode 100644 index 000000000..ffd519a6d --- /dev/null +++ b/crates/objc2/src/__macro_helpers/class.rs @@ -0,0 +1,107 @@ +use crate::{AllocAnyThread, ClassType, MainThreadOnly, ThreadKind}; + +/// Helper for ensuring that `ClassType::ThreadKind`, if specified, is set +/// correctly. +pub trait ValidThreadKind +where + Self: ClassType, + // Ensure the user did not attempt to declare or define a root class. + Self::Super: ClassType, +{ + // Required to reference the trait. + fn check() {} +} + +/// Always allow setting `MainThreadOnly`. +impl<'a, Cls> ValidThreadKind for Cls +where + Self: ClassType, + Self::Super: ClassType, +{ +} + +/// But restrict `AllocAnyThread` to only if the superclass also sets it. +impl<'a, 'b, Cls> ValidThreadKind for Cls +where + Self: ClassType, + Self::Super: ClassType, +{ +} + +/// Check that `MainThreadOnly` types do not implement `Send` and `Sync`. +/// +/// Check implemented using type inference: +/// let _ = >::check +pub trait MainThreadOnlyDoesNotImplSendSync { + // Required to reference the trait. + fn check() {} +} + +// Type inference will find this blanket impl... +impl MainThreadOnlyDoesNotImplSendSync<()> for Cls {} + +// ... unless one of these impls also apply, then type inference fails. +struct ImplsSend; +impl MainThreadOnlyDoesNotImplSendSync for Cls {} + +struct ImplsSync; +impl MainThreadOnlyDoesNotImplSendSync for Cls {} + +#[cfg(test)] +mod tests { + use super::*; + use crate::extern_class; + use crate::runtime::NSObject; + + extern_class!( + struct SetAnyThread; + + unsafe impl ClassType for SetAnyThread { + type Super = NSObject; + type ThreadKind = dyn AllocAnyThread; + const NAME: &'static str = "NSObject"; + } + ); + + extern_class!( + struct SendSync; + + unsafe impl ClassType for SendSync { + type Super = NSObject; + type ThreadKind = dyn AllocAnyThread; + const NAME: &'static str = "NSObject"; + } + ); + + unsafe impl Send for SendSync {} + unsafe impl Sync for SendSync {} + + extern_class!( + struct OnlyMain; + + unsafe impl ClassType for OnlyMain { + type Super = NSObject; + type ThreadKind = dyn MainThreadOnly; + const NAME: &'static str = "NSObject"; + } + ); + + extern_class!( + struct OnlyMainSubDefault; + + unsafe impl ClassType for OnlyMainSubDefault { + type Super = OnlyMain; + const NAME: &'static str = "NSObject"; + } + ); + + extern_class!( + struct OnlyMainSubExplicit; + + unsafe impl ClassType for OnlyMainSubExplicit { + type Super = OnlyMain; + type ThreadKind = dyn MainThreadOnly; + const NAME: &'static str = "NSObject"; + } + ); +} diff --git a/crates/objc2/src/__macro_helpers/declare_class.rs b/crates/objc2/src/__macro_helpers/declare_class.rs index dd58daf07..61dc4b7af 100644 --- a/crates/objc2/src/__macro_helpers/declare_class.rs +++ b/crates/objc2/src/__macro_helpers/declare_class.rs @@ -15,7 +15,6 @@ use crate::{ClassType, DeclaredClass, Message, ProtocolType}; use super::declared_ivars::{register_with_ivars, setup_dealloc}; use super::{CopyOrMutCopy, Init, MaybeUnwrap, New, Other}; -use crate::mutability; /// Helper type for implementing `MethodImplementation` with a receiver of /// `Allocated`, without exposing that implementation to users. @@ -134,37 +133,6 @@ impl MaybeOptionId for Option> { } } -/// Helper for ensuring that `ClassType::Mutability` is implemented correctly -/// for subclasses. -pub trait ValidSubclassMutability {} - -// Root -impl ValidSubclassMutability for mutability::Root {} -impl ValidSubclassMutability for mutability::Root {} - -// InteriorMutable -impl ValidSubclassMutability for mutability::InteriorMutable {} -impl ValidSubclassMutability for mutability::InteriorMutable {} - -// MainThreadOnly -impl ValidSubclassMutability for mutability::MainThreadOnly {} - -/// Ensure that: -/// 1. The type is not a root class (it's superclass implements `ClassType`, -/// and it's mutability is not `Root`), and therefore also implements basic -/// memory management methods, as required by `unsafe impl Message`. -/// 2. The mutability is valid according to the superclass' mutability. -#[inline] -pub fn assert_mutability_matches_superclass_mutability() -where - T: ?Sized + ClassType, - T::Super: ClassType, - T::Mutability: mutability::Mutability, - ::Mutability: ValidSubclassMutability, -{ - // Noop -} - #[derive(Debug)] pub struct ClassBuilderHelper { builder: ClassBuilder, diff --git a/crates/objc2/src/__macro_helpers/declared_ivars.rs b/crates/objc2/src/__macro_helpers/declared_ivars.rs index 0e67fc261..a60ecfe38 100644 --- a/crates/objc2/src/__macro_helpers/declared_ivars.rs +++ b/crates/objc2/src/__macro_helpers/declared_ivars.rs @@ -426,10 +426,9 @@ mod tests { use std::sync::Mutex; use super::*; - use crate::mutability::InteriorMutable; use crate::rc::{Allocated, PartialInit, RcTestObject, Retained, ThreadTestData}; use crate::runtime::NSObject; - use crate::{declare_class, msg_send, msg_send_id}; + use crate::{declare_class, msg_send, msg_send_id, AllocAnyThread}; /// Initialize superclasses, but not own class. unsafe fn init_only_superclasses(obj: Allocated) -> Retained @@ -492,7 +491,6 @@ mod tests { unsafe impl ClassType for ImplsDrop { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "ImplsDrop"; } @@ -533,7 +531,6 @@ mod tests { unsafe impl ClassType for IvarsImplDrop { type Super = ImplsDrop; - type Mutability = InteriorMutable; const NAME: &'static str = "IvarsImplDrop"; } @@ -568,7 +565,6 @@ mod tests { unsafe impl ClassType for BothIvarsAndTypeImplsDrop { type Super = IvarsImplDrop; - type Mutability = InteriorMutable; const NAME: &'static str = "BothIvarsAndTypeImplsDrop"; } @@ -625,7 +621,6 @@ mod tests { unsafe impl ClassType for IvarsNoDrop { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "IvarsNoDrop"; } @@ -652,7 +647,6 @@ mod tests { unsafe impl ClassType for IvarZst { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "IvarZst"; } @@ -695,7 +689,6 @@ mod tests { unsafe impl ClassType for HasIvarWithHighAlignment { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "HasIvarWithHighAlignment"; } @@ -726,7 +719,6 @@ mod tests { unsafe impl ClassType for RcIvar { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "RcIvar"; } @@ -793,7 +785,6 @@ mod tests { unsafe impl ClassType for RcIvarSubclass { type Super = RcIvar; - type Mutability = InteriorMutable; const NAME: &'static str = "RcIvarSubclass"; } @@ -864,7 +855,6 @@ mod tests { unsafe impl ClassType for InvalidAccess { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "InvalidAccess"; } @@ -887,7 +877,6 @@ mod tests { unsafe impl ClassType for DropPanics { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "DropPanics"; } @@ -922,7 +911,6 @@ mod tests { unsafe impl ClassType for IvarDropPanics { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "IvarDropPanics"; } diff --git a/crates/objc2/src/__macro_helpers/mod.rs b/crates/objc2/src/__macro_helpers/mod.rs index 905d59d33..194998684 100644 --- a/crates/objc2/src/__macro_helpers/mod.rs +++ b/crates/objc2/src/__macro_helpers/mod.rs @@ -11,6 +11,7 @@ pub use core::{compile_error, concat, panic, stringify}; pub use std::sync::Once; mod cache; +mod class; mod common_selectors; mod convert; mod declare_class; @@ -23,12 +24,11 @@ mod msg_send_id; mod writeback; pub use self::cache::{CachedClass, CachedSel}; +pub use self::class::{MainThreadOnlyDoesNotImplSendSync, ValidThreadKind}; pub use self::common_selectors::{alloc_sel, dealloc_sel, init_sel, new_sel}; pub use self::convert::{ConvertArgument, ConvertArguments, ConvertReturn, TupleExtender}; pub use self::declare_class::{ - assert_mutability_matches_superclass_mutability, ClassBuilderHelper, - ClassProtocolMethodsBuilder, IdReturnValue, MaybeOptionId, MessageRecieveId, - ValidSubclassMutability, + ClassBuilderHelper, ClassProtocolMethodsBuilder, IdReturnValue, MaybeOptionId, MessageRecieveId, }; pub use self::declared_ivars::DeclaredIvarsHelper; pub use self::image_info::ImageInfo; diff --git a/crates/objc2/src/__macro_helpers/msg_send.rs b/crates/objc2/src/__macro_helpers/msg_send.rs index 550ca66d0..9493ff701 100644 --- a/crates/objc2/src/__macro_helpers/msg_send.rs +++ b/crates/objc2/src/__macro_helpers/msg_send.rs @@ -184,9 +184,7 @@ impl MsgSend for ManuallyDrop> { mod tests { use crate::rc::{autoreleasepool, RcTestObject, ThreadTestData}; use crate::runtime::NSObject; - use crate::{ - declare_class, msg_send, msg_send_id, mutability, test_utils, ClassType, DeclaredClass, - }; + use crate::{declare_class, msg_send, msg_send_id, test_utils, ClassType, DeclaredClass}; use super::*; @@ -238,7 +236,6 @@ mod tests { unsafe impl ClassType for RcTestObjectSubclass { #[inherits(NSObject)] type Super = RcTestObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "RcTestObjectSubclass"; } diff --git a/crates/objc2/src/__macro_helpers/msg_send_id.rs b/crates/objc2/src/__macro_helpers/msg_send_id.rs index bca2744d5..0464b6445 100644 --- a/crates/objc2/src/__macro_helpers/msg_send_id.rs +++ b/crates/objc2/src/__macro_helpers/msg_send_id.rs @@ -524,7 +524,7 @@ mod tests { use crate::rc::{autoreleasepool, RcTestObject, ThreadTestData}; use crate::runtime::{NSObject, NSZone}; - use crate::{class, msg_send_id}; + use crate::{class, msg_send_id, AllocAnyThread}; mod test_trait_disambugated { use super::*; diff --git a/crates/objc2/src/lib.rs b/crates/objc2/src/lib.rs index d4fe7101a..867466072 100644 --- a/crates/objc2/src/lib.rs +++ b/crates/objc2/src/lib.rs @@ -21,7 +21,7 @@ //! //! This example illustrates major parts of the functionality in this crate: //! -//! First, we allocate a new [`NSObject`] using [`ClassType::alloc`]. +//! First, we allocate a new [`NSObject`] using [`AllocAnyThread::alloc`]. //! Next, we initialize this object. It is ensured to be deallocated using //! [`rc::Retained`]. //! Now we're free to send messages to the object to our hearts desire using @@ -31,7 +31,7 @@ //! deallocated. //! //! ``` -//! use objc2::{msg_send, msg_send_id, ClassType}; +//! use objc2::{msg_send, msg_send_id, AllocAnyThread, ClassType}; //! use objc2::ffi::NSUInteger; //! use objc2::rc::Retained; //! use objc2::runtime::{NSObject, NSObjectProtocol}; @@ -173,7 +173,9 @@ extern crate std; #[doc(no_inline)] pub use self::encode::{Encode, Encoding, RefEncode}; pub use self::main_thread_marker::MainThreadMarker; -pub use self::top_level_traits::{ClassType, DeclaredClass, Message, ProtocolType}; +pub use self::top_level_traits::{ + AllocAnyThread, ClassType, DeclaredClass, MainThreadOnly, Message, ProtocolType, ThreadKind, +}; #[cfg(feature = "objc2-proc-macros")] #[doc(hidden)] @@ -200,7 +202,6 @@ pub mod exception; pub mod ffi; mod macros; mod main_thread_marker; -pub mod mutability; pub mod rc; pub mod runtime; #[cfg(test)] diff --git a/crates/objc2/src/macros/declare_class.rs b/crates/objc2/src/macros/declare_class.rs index c39972ced..3d1e78472 100644 --- a/crates/objc2/src/macros/declare_class.rs +++ b/crates/objc2/src/macros/declare_class.rs @@ -168,7 +168,6 @@ /// `unsafe impl ClassType for T` has the following safety requirements: /// - Any invariants that the superclass [`ClassType::Super`] may have must be /// upheld. -/// - [`ClassType::Mutability`] must be correct. /// - If your type implements `Drop`, the implementation must abide by the /// following rules: /// - It must not call any overridden methods. @@ -189,7 +188,6 @@ /// this definition has the same safety requirements as above. /// /// [`ClassType::Super`]: crate::ClassType::Super -/// [`ClassType::Mutability`]: crate::ClassType::Mutability /// [Open an issue]: https://github.com/madsmtm/objc2/issues/new /// /// @@ -206,8 +204,8 @@ /// use objc2_foundation::{NSCopying, NSObject, NSObjectProtocol, NSZone}; /// use objc2::rc::{Allocated, Retained}; /// use objc2::{ -/// declare_class, extern_protocol, msg_send, msg_send_id, mutability, ClassType, -/// DeclaredClass, ProtocolType, +/// declare_class, extern_protocol, msg_send, msg_send_id, AllocAnyThread, +/// ClassType, DeclaredClass, ProtocolType, /// }; /// /// #[derive(Clone)] @@ -222,11 +220,12 @@ /// /// // SAFETY: /// // - The superclass NSObject does not have any subclassing requirements. -/// // - Interior mutability is a safe default. /// // - `MyCustomObject` does not implement `Drop`. /// unsafe impl ClassType for MyCustomObject { /// type Super = NSObject; -/// type Mutability = mutability::InteriorMutable; +/// // If we were implementing delegate methods like `NSApplicationDelegate`, +/// // we would specify the object to only be usable on the main thread: +/// // type ThreadKind = dyn MainThreadOnly; /// const NAME: &'static str = "MyCustomObject"; /// } /// @@ -387,7 +386,7 @@ macro_rules! declare_class { $(#[inherits($($inheritance_rest:ty),+)])? type Super = $superclass:ty; - type Mutability = $mutability:ty; + $(type ThreadKind = $thread_kind:ty;)? const NAME: &'static str = $name_const:expr; } @@ -427,11 +426,14 @@ macro_rules! declare_class { // Creation unsafe impl ClassType for $for_class { type Super = $superclass; - type Mutability = $mutability; + + type ThreadKind = $crate::__select_thread_kind!($($thread_kind)?); + const NAME: &'static $crate::__macro_helpers::str = $name_const; fn class() -> &'static $crate::runtime::AnyClass { - $crate::__macro_helpers::assert_mutability_matches_superclass_mutability::(); + let _ = >::check; + let _ = >::check; // TODO: Use `std::sync::OnceLock` static REGISTER_CLASS: $crate::__macro_helpers::Once = $crate::__macro_helpers::Once::new(); @@ -518,17 +520,6 @@ macro_rules! declare_class { }; } -#[doc(hidden)] -#[macro_export] -macro_rules! __select_name { - ($_name:ident; $name_const:expr) => { - $name_const - }; - ($name:ident;) => { - $crate::__macro_helpers::stringify!($name) - }; -} - #[doc(hidden)] #[macro_export] macro_rules! __select_ivars { diff --git a/crates/objc2/src/macros/extern_class.rs b/crates/objc2/src/macros/extern_class.rs index 94f1eec6f..6164b61c2 100644 --- a/crates/objc2/src/macros/extern_class.rs +++ b/crates/objc2/src/macros/extern_class.rs @@ -47,7 +47,8 @@ /// would not give you the ability to convert via. `AsRef` to `NSObject`. /// Therefore, you may optionally specify additional parts of the /// inheritance chain using an `#[inherits(...)]` attribute. -/// - The class' [`Mutability`]. +/// - Optionally, the class' [`ThreadKind`], if the object is only usable on +/// the main thread. /// - Optionally, the class' [`NAME`] - if not specified, this will default to /// the struct name. /// @@ -56,7 +57,7 @@ /// /// [`ClassType`]: crate::ClassType /// [`Super`]: crate::ClassType::Super -/// [`Mutability`]: crate::ClassType::Mutability +/// [`ThreadKind`]: crate::ClassType::ThreadKind /// [`NAME`]: crate::ClassType::NAME /// /// @@ -69,15 +70,13 @@ /// In particular, when writing `unsafe` on `impl ClassType`, you must ensure /// that: /// 1. [`ClassType::Super`] is correct. -/// 2. [`ClassType::Mutability`] is correct. -/// -/// See [`ClassType`'s safety section][ClassType#safety] for further -/// details on what this entails. +/// 2. [`ClassType::ThreadKind`] is correctly set to `MainThreadOnly` if the +/// class can only be used from the main thread. /// /// [`RefEncode`]: crate::encode::RefEncode /// [`Message`]: crate::Message /// [`ClassType::Super`]: crate::ClassType::Super -/// [`ClassType::Mutability`]: crate::ClassType::Mutability +/// [`ClassType::ThreadKind`]: crate::ClassType::ThreadKind /// [ClassType#safety]: crate::ClassType#safety /// /// @@ -92,7 +91,7 @@ /// # use objc2::runtime::NSObjectProtocol; /// use objc2::rc::Retained; /// use objc2::runtime::NSObject; -/// use objc2::{extern_class, msg_send_id, mutability, ClassType}; +/// use objc2::{extern_class, msg_send_id, ClassType}; /// /// extern_class!( /// /// An example description. @@ -100,10 +99,13 @@ /// // Specify the class and struct name to be used /// pub struct NSFormatter; /// -/// // Specify the superclass, in this case `NSObject` /// unsafe impl ClassType for NSFormatter { +/// // Specify the superclass, in this case `NSObject` /// type Super = NSObject; -/// type Mutability = mutability::InteriorMutable; +/// +/// // Optionally, specify that the class is only usable on the main thread. +/// // type ThreadKind = dyn MainThreadOnly; +/// /// // Optionally, specify the name of the class, if it differs from /// // the struct name. /// // const NAME: &'static str = "NSFormatter"; @@ -135,7 +137,7 @@ /// use objc2_foundation::{NSCoding, NSCopying, NSObjectProtocol}; /// # use objc2::runtime::NSObjectProtocol; /// use objc2::runtime::NSObject; -/// use objc2::{extern_class, mutability, ClassType}; +/// use objc2::{extern_class, ClassType}; /// # /// # extern_class!( /// # #[derive(PartialEq, Eq, Hash)] @@ -143,7 +145,6 @@ /// # /// # unsafe impl ClassType for NSFormatter { /// # type Super = NSObject; -/// # type Mutability = mutability::InteriorMutable; /// # } /// # ); /// @@ -155,7 +156,6 @@ /// // Specify the correct inheritance chain /// #[inherits(NSObject)] /// type Super = NSFormatter; -/// type Mutability = mutability::InteriorMutable; /// } /// ); /// @@ -180,8 +180,7 @@ macro_rules! extern_class { unsafe impl ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? type Super = $superclass:ty; - type Mutability = $mutability:ty; - + $(type ThreadKind = $thread_kind:ty;)? $(const NAME: &'static str = $name_const:expr;)? } ) => { @@ -194,8 +193,7 @@ macro_rules! extern_class { unsafe impl ClassType for $for { $(#[inherits($($inheritance_rest),+)])? type Super = $superclass; - type Mutability = $mutability; - + $(type ThreadKind = $thread_kind;)? $(const NAME: &'static str = $name_const;)? } ); @@ -210,8 +208,7 @@ macro_rules! extern_class { unsafe impl ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? type Super = $superclass:ty; - type Mutability = $mutability:ty; - + $(type ThreadKind = $thread_kind:ty;)? $(const NAME: &'static str = $name_const:expr;)? } ) => { @@ -222,17 +219,26 @@ macro_rules! extern_class { $($field_vis $field: $field_ty,)* } + // SAFETY: + // 1. We define the type, and ensure that it represents a specific + // class (for example with the check below that ensures it is + // zero-sized). + // 2. Caller upholds that the superclass is correct. + // 3. [`Self::ThreadKind`] is ensured correct by `ValidThreadKind` + // and `MainThreadOnlyDoesNotImplSendSync` in `class`. + // 4. While the user controls the name, they control it in a way + // that... + // 5. [`class`] still returns the actual class. $(#[$impl_m])* unsafe impl<> ClassType for $for { $(#[inherits($($inheritance_rest),+)])? type Super = $superclass; - type Mutability = $mutability; + $(type ThreadKind = $thread_kind;)? + $(const NAME: &'static str = $name_const;)? fn as_super(&self) -> &Self::Super { &self.__superclass } - - $(const NAME: &'static str = $name_const;)? } ); @@ -309,11 +315,10 @@ macro_rules! __inner_extern_class { unsafe impl<$($t_for:ident $(: $(?$b_sized_for:ident +)? $b_for:ident)?),* $(,)?> ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+ $(,)?)])? type Super = $superclass:ty; - type Mutability = $mutability:ty; + $(type ThreadKind = $thread_kind:ty;)? + $(const NAME: &'static str = $name_const:expr;)? fn as_super(&$as_super_self:ident) -> &Self::Super $as_super:block - - $(const NAME: &'static str = $name_const:expr;)? } ) => { $(#[$m])* @@ -335,12 +340,13 @@ macro_rules! __inner_extern_class { $(#[$impl_m])* unsafe impl<$($t_for $(: $(?$b_sized_for +)? $b_for)?),*> ClassType for $for { type Super = $superclass; - type Mutability = $mutability; + type ThreadKind = $crate::__select_thread_kind!($($thread_kind)?); const NAME: &'static $crate::__macro_helpers::str = $crate::__select_name!($name; $($name_const)?); #[inline] fn class() -> &'static $crate::runtime::AnyClass { - $crate::__macro_helpers::assert_mutability_matches_superclass_mutability::(); + let _ = >::check; + let _ = >::check; $crate::__class_inner!( $crate::__select_name!($name; $($name_const)?), @@ -391,10 +397,9 @@ macro_rules! __extern_class_impl_traits { // // That the object must work with standard memory management is // properly upheld by the fact that the superclass is required by - // `assert_mutability_matches_superclass_mutability` to implement - // `ClassType`, and hence must be a subclass of one of `NSObject`, - // `NSProxy` or some other class that ensures this (e.g. the object - // itself is not a root class). + // `ValidThreadKind` to implement `ClassType`, and hence must also be + // a subclass of one of `NSObject`, `NSProxy` or some other class that + // ensures this (e.g. the object itself is not a root class). $(#[$impl_m])* unsafe impl<$($t)*> $crate::Message for $for {} @@ -445,3 +450,26 @@ macro_rules! __extern_class_impl_traits { } }; } + +#[doc(hidden)] +#[macro_export] +macro_rules! __select_thread_kind { + () => { + // Default to the super class' thread kind + ::ThreadKind + }; + ($thread_kind:ty) => { + $thread_kind + }; +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __select_name { + ($_name:ident; $name_const:expr) => { + $name_const + }; + ($name:ident;) => { + $crate::__macro_helpers::stringify!($name) + }; +} diff --git a/crates/objc2/src/macros/extern_methods.rs b/crates/objc2/src/macros/extern_methods.rs index 05457bfb9..d3139ceab 100644 --- a/crates/objc2/src/macros/extern_methods.rs +++ b/crates/objc2/src/macros/extern_methods.rs @@ -69,7 +69,7 @@ /// use objc2::ffi::NSUInteger; /// use objc2::rc::{Allocated, Retained}; /// use objc2::runtime::NSObject; -/// use objc2::{declare_class, extern_methods, mutability, ClassType, DeclaredClass}; +/// use objc2::{declare_class, extern_methods, ClassType, DeclaredClass}; /// /// // Shim /// type NSError = NSObject; @@ -79,11 +79,9 @@ /// /// // SAFETY: /// // - The superclass NSObject does not have any subclassing requirements. -/// // - Interior mutability is a safe default. /// // - `MyObject` does not implement `Drop`. /// unsafe impl ClassType for MyObject { /// type Super = NSObject; -/// type Mutability = mutability::InteriorMutable; /// const NAME: &'static str = "MyObject"; /// } /// @@ -129,7 +127,7 @@ /// # use objc2::ffi::NSUInteger; /// # use objc2::rc::{Allocated, Retained}; /// # use objc2::runtime::NSObject; -/// # use objc2::{declare_class, extern_methods, mutability, ClassType, DeclaredClass}; +/// # use objc2::{declare_class, extern_methods, ClassType, DeclaredClass}; /// # /// # // Shim /// # type NSError = NSObject; @@ -139,7 +137,6 @@ /// # /// # unsafe impl ClassType for MyObject { /// # type Super = NSObject; -/// # type Mutability = mutability::InteriorMutable; /// # const NAME: &'static str = "MyObject2"; /// # } /// # diff --git a/crates/objc2/src/macros/mod.rs b/crates/objc2/src/macros/mod.rs index 7ce4ec32f..c3862136a 100644 --- a/crates/objc2/src/macros/mod.rs +++ b/crates/objc2/src/macros/mod.rs @@ -908,14 +908,13 @@ macro_rules! __class_inner { /// use objc2::msg_send; /// # /// # use objc2::runtime::NSObject; -/// # use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +/// # use objc2::{declare_class, ClassType, DeclaredClass}; /// # /// # declare_class!( /// # struct MyObject; /// # /// # unsafe impl ClassType for MyObject { /// # type Super = NSObject; -/// # type Mutability = mutability::InteriorMutable; /// # const NAME: &'static str = "MyObject"; /// # } /// # diff --git a/crates/objc2/src/main_thread_marker.rs b/crates/objc2/src/main_thread_marker.rs index a7e9748be..3072a242f 100644 --- a/crates/objc2/src/main_thread_marker.rs +++ b/crates/objc2/src/main_thread_marker.rs @@ -1,9 +1,8 @@ use core::fmt; use core::marker::PhantomData; -use crate::mutability::IsMainThreadOnly; use crate::rc::Allocated; -use crate::ClassType; +use crate::{msg_send_id, ClassType, MainThreadOnly}; /// Whether the current thread is the main thread. #[inline] @@ -152,21 +151,22 @@ impl MainThreadMarker { /// Allocate a new instance of the specified class on the main thread. /// - /// This is a soft-deprecated shorthand for - /// [`ClassType::alloc_main_thread`], it will be fully deprecated once - /// [arbitrary self types][tracking] become stable. - /// - /// [tracking]: https://github.com/rust-lang/rust/issues/44874 + /// This can be useful in certain situations, such as generic contexts + /// where you don't know whether the class is main thread or not, but + /// usually you should prefer [`MainThreadOnly::alloc`]. #[inline] pub fn alloc(self) -> Allocated { - T::alloc_main_thread(self) + // SAFETY: We hold `MainThreadMarker`, and classes are either only + // safe to allocate on the main thread, or safe to allocate + // everywhere. + unsafe { msg_send_id![T::class(), alloc] } } } /// Get a [`MainThreadMarker`] from a main-thread-only object. /// -/// This is a soft-deprecated shorthand for [`IsMainThreadOnly::mtm`]. -impl From<&T> for MainThreadMarker { +/// This is a shorthand for [`MainThreadOnly::mtm`]. +impl From<&T> for MainThreadMarker { #[inline] fn from(obj: &T) -> Self { obj.mtm() diff --git a/crates/objc2/src/mutability.rs b/crates/objc2/src/mutability.rs deleted file mode 100644 index f51740699..000000000 --- a/crates/objc2/src/mutability.rs +++ /dev/null @@ -1,241 +0,0 @@ -//! # Marker types for class mutability. -//! -//! Every class must indicate which kind of mutability its instances use: -//! - Is the instance mutable or immutable? -//! - Does it use interior mutability (mutable behind `&self`, like -//! [`UnsafeCell`])? -//! - Does it access global statics in such a way that the type is only safe -//! to use from the main thread? -//! -//! The answer to these facts influence the final capabilities the type has, -//! as encoded in [the traits in this module](#traits). -//! -//! Concretely, you set [`ClassType::Mutability`] to [one of the types in this -//! module](#structs) to indicate the properties of class you're dealing with -//! (can be done inside [`extern_class!`] and [`declare_class!`]). -//! -//! Note that precious little of Objective-C follows Rust's usual shared xor -//! unique ownership model, most often objects assume interior mutability, so -//! a safe default is often [`InteriorMutable`], or of you're working with GUI -//! code, [`MainThreadOnly`]. -//! -//! An explicit design decision in `objc2` is that once you type-erase a -//! mutable object, you are allowed to do normal reference-counting with it -//! (that's also an implicit assumption in Objective-C, e.g. classes are -//! allowed to pass `NSString` in their public API, while actually giving -//! access to a `NSMutableString`). -//! -//! [`UnsafeCell`]: core::cell::UnsafeCell -//! [`ClassType::Mutability`]: crate::ClassType::Mutability -//! [`extern_class!`]: crate::extern_class -//! [`declare_class!`]: crate::declare_class -//! -//! -//! # SemVer -//! -//! It is considered a major change to change the [`ClassType::Mutability`] of -//! an object, though it can be done as a minor change in some cases to fix a -//! bug. -use crate::runtime::{AnyObject, ProtocolObject}; -use crate::{ClassType, MainThreadMarker}; - -mod private_mutability { - pub trait Sealed {} -} - -/// Marker trait for the different types of mutability a class can have. -/// -/// This is a sealed trait, and should not need to be implemented. Open an -/// issue if you know a use-case where this restrition should be lifted! -// -// Note: `Sized` is intentionally added to make the trait not object safe. -pub trait Mutability: private_mutability::Sealed + Sized {} - -impl private_mutability::Sealed for Root {} -impl Mutability for Root {} - -impl private_mutability::Sealed for InteriorMutable {} -impl Mutability for InteriorMutable {} - -impl private_mutability::Sealed for MainThreadOnly {} -impl Mutability for MainThreadOnly {} - -/// Helper to make the structs uninhabited, without that being a public fact. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -enum Never {} - -/// Marker type for root classes. -/// -/// This is used for `objc2_foundation::NSObject` and -/// `objc2_foundation::NSProxy`, which are the two fundamental types that -/// all others inherit from. -/// -/// Functionality that is provided with this: -/// - [`IsAllocableAnyThread`] -> [`ClassType::alloc`]. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct Root { - inner: Never, -} - -/// Marker type for classes that use interior mutability. -/// -/// This is usually not `Send + Sync`, unless the class is guaranteed to use -/// thread-safe operations. -/// -/// Functionality that is provided with this: -/// - [`IsAllocableAnyThread`] -> [`ClassType::alloc`]. -/// -/// -/// # Safety notice -/// -/// When declaring classes, it is recommended that you wrap your instance -/// variables in [`Cell`], [`RefCell`], atomics or other similar interior -/// mutability abstractions to allow mutating your instance variables through -/// `&self`. -/// -/// Declared classes that use this cannot take `&mut self`, except in -/// initializers. -/// -/// [`Cell`]: core::cell::Cell -/// [`RefCell`]: core::cell::RefCell -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct InteriorMutable { - inner: Never, -} - -/// Marker type for classes that are only safe to use from the main thread. -/// -/// This is effectively the same as [`InteriorMutable`], except that classes -/// that specify this are only allowed to be used from the main thread, and -/// hence are not [`IsAllocableAnyThread`]. -/// -/// This is commonly used in GUI code like `AppKit` and `UIKit`, e.g. -/// `UIWindow` is only usable from the application's main thread. -/// -/// It is unsound to implement [`Send`] or [`Sync`] on a type with this -/// mutability. -/// -/// Functionality that is provided with this: -/// - [`IsMainThreadOnly`] -> `IsMainThreadOnly::mtm`. -// -// While Xcode's Main Thread Checker doesn't report `alloc` and `dealloc` as -// unsafe from other threads, things like `NSView` and `NSWindow` still do a -// non-trivial amount of stuff on `dealloc`, even if the object is freshly -// `alloc`'d - so let's disallow that to be sure. -// -// This also has the nice property that `Allocated` is guaranteed to be -// allowed to initialize on the current thread. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -pub struct MainThreadOnly { - inner: Never, -} - -mod private_traits { - pub trait Sealed {} -} - -impl private_traits::Sealed for T {} -impl private_traits::Sealed for ProtocolObject

{} -impl private_traits::Sealed for AnyObject {} - -/// Marker trait for classes that can be allocated from any thread. -/// -/// This is implemented for classes whose [`ClassType::Mutability`] is one of: -/// - [`Root`]. -/// - [`InteriorMutable`]. -/// -/// -/// # Safety -/// -/// This is a sealed trait, and should not need to be implemented. Open an -/// issue if you know a use-case where this restrition should be lifted! -pub unsafe trait IsAllocableAnyThread: private_traits::Sealed {} - -trait MutabilityIsAllocableAnyThread: Mutability {} -impl MutabilityIsAllocableAnyThread for Root {} -impl MutabilityIsAllocableAnyThread for InteriorMutable {} - -unsafe impl IsAllocableAnyThread for T where - T::Mutability: MutabilityIsAllocableAnyThread -{ -} -unsafe impl IsAllocableAnyThread for ProtocolObject

{} - -/// Marker trait for classes that are only available on the main thread. -/// -/// This is implemented for classes whose [`ClassType::Mutability`] is one of: -/// - [`MainThreadOnly`]. -/// -/// Since `MainThreadOnly` types must be `!Send` and `!Sync`, if you hold a -/// type that implements this trait, then you're guaranteed to be on the main -/// thread (and can get a `MainThreadMarker` using `IsMainThreadOnly::mtm`). -/// -/// -/// # Safety -/// -/// This is a sealed trait, and should not need to be implemented. Open an -/// issue if you know a use-case where this restrition should be lifted! -pub unsafe trait IsMainThreadOnly: private_traits::Sealed { - /// Get a [`MainThreadMarker`] from a main-thread-only object. - /// - /// This function exists purely in the type-system, and will succeed at - /// runtime (with a safety check when debug assertions are enabled). - #[inline] - #[cfg_attr(debug_assertions, track_caller)] - fn mtm(&self) -> MainThreadMarker { - #[cfg(debug_assertions)] - assert!( - MainThreadMarker::new().is_some(), - "the main-thread-only object that we tried to fetch a MainThreadMarker from was somehow not on the main thread", - ); - - // SAFETY: Objects which are `IsMainThreadOnly` are guaranteed - // `!Send + !Sync` and are only constructible on the main thread. - // - // Since we hold a reference to such an object, and we know it cannot - // now possibly be on another thread than the main, we know that the - // current thread is the main thread. - unsafe { MainThreadMarker::new_unchecked() } - } -} - -trait MutabilityIsMainThreadOnly: Mutability {} -impl MutabilityIsMainThreadOnly for MainThreadOnly {} - -unsafe impl IsMainThreadOnly for T where - T::Mutability: MutabilityIsMainThreadOnly -{ -} -unsafe impl IsMainThreadOnly for ProtocolObject

{} - -#[cfg(test)] -mod tests { - use super::*; - - use core::fmt; - use core::hash; - - #[test] - fn generic_traits() { - fn assert_traits() - where - T: Sync + Send, - T: Clone + Copy + PartialEq + Eq + PartialOrd + Ord + hash::Hash + fmt::Debug, - { - } - - assert_traits::(); - assert_traits::(); - assert_traits::(); - - #[allow(unused)] - #[allow(clippy::needless_maybe_sized)] - fn test_mutability_implies_sized() { - fn assert_sized() {} - assert_sized::(); - } - } - - #[allow(unused, clippy::too_many_arguments)] - fn object_safe(_: &dyn IsAllocableAnyThread, _: &dyn IsMainThreadOnly) {} -} diff --git a/crates/objc2/src/rc/id.rs b/crates/objc2/src/rc/id.rs index 908f62df3..fd44cf2e1 100644 --- a/crates/objc2/src/rc/id.rs +++ b/crates/objc2/src/rc/id.rs @@ -93,8 +93,6 @@ use crate::{ffi, ClassType, Message}; /// # /// # unsafe impl ClassType for NSString { /// # type Super = NSObject; -/// # // This is wrong, but let's do it for the example -/// # type Mutability = objc2::mutability::InteriorMutable; /// # } /// # ); /// @@ -198,7 +196,7 @@ impl Retained { /// ``` /// use objc2::rc::Retained; /// use objc2::runtime::NSObject; - /// use objc2::{msg_send, msg_send_id, ClassType}; + /// use objc2::{msg_send, msg_send_id, AllocAnyThread, ClassType}; /// /// // Manually using `msg_send!` and `Retained::from_raw` /// let obj: *mut NSObject = unsafe { msg_send![NSObject::class(), alloc] }; @@ -744,7 +742,6 @@ mod tests { use static_assertions::{assert_impl_all, assert_not_impl_any}; use super::*; - use crate::mutability::InteriorMutable; use crate::rc::{autoreleasepool, RcTestObject, ThreadTestData}; use crate::runtime::{AnyObject, NSObject, NSObjectProtocol}; use crate::{declare_class, msg_send, DeclaredClass}; @@ -752,13 +749,12 @@ mod tests { #[test] fn auto_traits() { macro_rules! helper { - ($name:ident, $mutability:ty) => { + ($name:ident) => { declare_class!( struct $name; unsafe impl ClassType for $name { type Super = NSObject; - type Mutability = $mutability; const NAME: &'static str = concat!(stringify!($name), "Test"); } @@ -767,12 +763,12 @@ mod tests { }; } - helper!(Object, InteriorMutable); - helper!(SendObject, InteriorMutable); + helper!(Object); + helper!(SendObject); unsafe impl Send for SendObject {} - helper!(SyncObject, InteriorMutable); + helper!(SyncObject); unsafe impl Sync for SyncObject {} - helper!(SendSyncObject, InteriorMutable); + helper!(SendSyncObject); unsafe impl Send for SendSyncObject {} unsafe impl Sync for SendSyncObject {} diff --git a/crates/objc2/src/rc/id_traits.rs b/crates/objc2/src/rc/id_traits.rs index b9799b0d5..c0de5d599 100644 --- a/crates/objc2/src/rc/id_traits.rs +++ b/crates/objc2/src/rc/id_traits.rs @@ -144,7 +144,6 @@ impl> FromIterator for Retained { #[cfg(test)] mod tests { use super::*; - use crate::mutability::InteriorMutable; use crate::runtime::NSObject; use crate::{declare_class, msg_send_id, ClassType, DeclaredClass}; @@ -154,7 +153,6 @@ mod tests { unsafe impl ClassType for Collection { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "MyCustomCollection"; } diff --git a/crates/objc2/src/rc/test_object.rs b/crates/objc2/src/rc/test_object.rs index 34380e71b..5cdca79de 100644 --- a/crates/objc2/src/rc/test_object.rs +++ b/crates/objc2/src/rc/test_object.rs @@ -2,7 +2,6 @@ use core::cell::RefCell; use core::ptr; -use crate::mutability::InteriorMutable; use crate::rc::{Allocated, DefaultRetained, Retained}; use crate::runtime::{NSObject, NSZone}; use crate::{declare_class, msg_send, msg_send_id, ClassType, DeclaredClass}; @@ -70,7 +69,6 @@ declare_class!( unsafe impl ClassType for RcTestObject { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "__RcTestObject"; } diff --git a/crates/objc2/src/runtime/declare.rs b/crates/objc2/src/runtime/declare.rs index 4e5a15239..63edcf1fc 100644 --- a/crates/objc2/src/runtime/declare.rs +++ b/crates/objc2/src/runtime/declare.rs @@ -571,7 +571,6 @@ mod tests { use super::*; use crate::encode::RefEncode; - use crate::mutability::InteriorMutable; use crate::rc::Retained; use crate::runtime::{NSObject, NSObjectProtocol}; use crate::{ @@ -843,7 +842,7 @@ mod tests { unsafe impl ClassType for GenericDeclareClass { type Super = NSObject; - type Mutability = InteriorMutable; + type ThreadKind = ::ThreadKind; const NAME: &'static str = "GenericDeclareClass"; #[inline] @@ -881,7 +880,6 @@ mod tests { unsafe impl ClassType for Custom { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestInheritedNSObjectMethodsWork"; } diff --git a/crates/objc2/src/runtime/nsobject.rs b/crates/objc2/src/runtime/nsobject.rs index f969ed63c..887c89be9 100644 --- a/crates/objc2/src/runtime/nsobject.rs +++ b/crates/objc2/src/runtime/nsobject.rs @@ -2,11 +2,11 @@ use core::fmt; use core::hash; use crate::ffi::NSUInteger; -use crate::mutability::Root; use crate::rc::{Allocated, DefaultRetained, Retained}; use crate::runtime::{AnyClass, AnyObject, AnyProtocol, ImplementedBy, ProtocolObject, Sel}; -use crate::{extern_methods, msg_send, msg_send_id, Message}; -use crate::{ClassType, ProtocolType}; +use crate::{ + extern_methods, msg_send, msg_send_id, AllocAnyThread, ClassType, Message, ProtocolType, +}; /// The root class of most Objective-C class hierarchies. /// @@ -37,7 +37,7 @@ crate::__extern_class_impl_traits! { unsafe impl ClassType for NSObject { type Super = AnyObject; - type Mutability = Root; + type ThreadKind = dyn AllocAnyThread; const NAME: &'static str = "NSObject"; #[inline] @@ -363,8 +363,10 @@ extern_methods!( unsafe impl NSObject { /// Create a new empty `NSObject`. /// - /// This method is a shorthand for calling [`alloc`][ClassType::alloc] - /// and then [`init`][Self::init]. + /// This method is a shorthand for calling [`alloc`] and then + /// [`init`][Self::init]. + /// + /// [`alloc`]: AllocAnyThread::alloc #[method_id(new)] pub fn new() -> Retained; @@ -379,7 +381,7 @@ extern_methods!( /// /// ``` /// use objc2::runtime::NSObject; - /// use objc2::ClassType; + /// use objc2::AllocAnyThread; /// /// let obj = NSObject::init(NSObject::alloc()); /// ``` @@ -457,7 +459,6 @@ mod tests { use alloc::format; use crate::extern_class; - use crate::mutability::InteriorMutable; use crate::rc::RcTestObject; extern_class!( @@ -466,7 +467,6 @@ mod tests { unsafe impl ClassType for FakeSubclass { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "NSObject"; } ); diff --git a/crates/objc2/src/runtime/nsproxy.rs b/crates/objc2/src/runtime/nsproxy.rs index 3e3d9fdc0..d3a6e150a 100644 --- a/crates/objc2/src/runtime/nsproxy.rs +++ b/crates/objc2/src/runtime/nsproxy.rs @@ -1,9 +1,8 @@ use core::fmt; use core::hash; -use crate::mutability::Root; use crate::runtime::{AnyClass, AnyObject, NSObjectProtocol, ProtocolObject}; -use crate::ClassType; +use crate::{AllocAnyThread, ClassType}; /// An abstract superclass defining an API for objects that act as /// stand-ins for other objects or for objects that don’t exist yet. @@ -28,7 +27,7 @@ crate::__extern_class_impl_traits! { unsafe impl ClassType for NSProxy { type Super = AnyObject; - type Mutability = Root; + type ThreadKind = dyn AllocAnyThread; const NAME: &'static str = "NSProxy"; #[inline] diff --git a/crates/objc2/src/runtime/protocol_object.rs b/crates/objc2/src/runtime/protocol_object.rs index 52cde9138..292a0ddb2 100644 --- a/crates/objc2/src/runtime/protocol_object.rs +++ b/crates/objc2/src/runtime/protocol_object.rs @@ -198,7 +198,6 @@ mod tests { use static_assertions::{assert_impl_all, assert_not_impl_any}; use super::*; - use crate::mutability::InteriorMutable; use crate::runtime::NSObject; use crate::{ declare_class, extern_methods, extern_protocol, ClassType, DeclaredClass, ProtocolType, @@ -258,7 +257,6 @@ mod tests { unsafe impl ClassType for DummyClass { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "ProtocolTestsDummyClass"; } diff --git a/crates/objc2/src/test_utils.rs b/crates/objc2/src/test_utils.rs index 882d6bd24..b2841a9f8 100644 --- a/crates/objc2/src/test_utils.rs +++ b/crates/objc2/src/test_utils.rs @@ -5,7 +5,7 @@ use std::sync::Once; use crate::encode::{Encode, Encoding, RefEncode}; use crate::rc::Retained; use crate::runtime::{AnyClass, AnyObject, AnyProtocol, ClassBuilder, ProtocolBuilder, Sel}; -use crate::{ffi, msg_send, mutability, sel, ClassType, Message}; +use crate::{ffi, msg_send, sel, AllocAnyThread, ClassType, Message}; #[derive(Debug)] #[repr(C)] @@ -19,9 +19,7 @@ unsafe impl Message for CustomObject {} unsafe impl ClassType for CustomObject { type Super = AnyObject; - - type Mutability = mutability::InteriorMutable; - + type ThreadKind = dyn AllocAnyThread; const NAME: &'static str = "CustomObject"; fn class() -> &'static AnyClass { diff --git a/crates/objc2/src/top_level_traits.rs b/crates/objc2/src/top_level_traits.rs index 14406d647..b7b74538a 100644 --- a/crates/objc2/src/top_level_traits.rs +++ b/crates/objc2/src/top_level_traits.rs @@ -2,9 +2,8 @@ use core::ptr::NonNull; use crate::__macro_helpers::declared_ivars::get_initialized_ivar_ptr; use crate::encode::RefEncode; -use crate::mutability::{IsAllocableAnyThread, Mutability}; use crate::rc::{Allocated, Retained}; -use crate::runtime::{AnyClass, AnyProtocol}; +use crate::runtime::{AnyClass, AnyProtocol, ProtocolObject}; use crate::{msg_send_id, MainThreadMarker}; /// Types that can be sent Objective-C messages. @@ -131,16 +130,12 @@ pub unsafe trait Message: RefEncode { /// 1. The type must represent a specific class. /// 2. [`Self::Super`] must be a superclass of the class (or something that /// represents any object, like [`AnyObject`][crate::runtime::AnyObject]). -/// 3. [`Self::Mutability`] must be specified correctly. -/// -/// If you're unsure of what to do, [`InteriorMutable`] is usually a good -/// starting point. -/// 4. [`Self::NAME`] must be correct. +/// 3. [`Self::ThreadKind`] must be correct. It is safe to default to the +/// super class' thread kind, `::ThreadKind`. +/// 4. [`Self::NAME`] must be the name of the class that this type represents. /// 5. The class returned by [`Self::class`] must be the class that this type /// represents. /// -/// [`InteriorMutable`]: crate::mutability::InteriorMutable -/// /// /// # Examples /// @@ -170,7 +165,7 @@ pub unsafe trait Message: RefEncode { /// Use the trait to allocate a new instance of an object. /// /// ``` -/// use objc2::{ClassType, msg_send_id}; +/// use objc2::{msg_send_id, AllocAnyThread}; /// use objc2::rc::Retained; /// # use objc2::runtime::{NSObject as MyObject}; /// @@ -187,15 +182,15 @@ pub unsafe trait Message: RefEncode { /// /// ``` /// use objc2::runtime::NSObject; -/// use objc2::{extern_class, mutability, ClassType}; +/// use objc2::{extern_class, ClassType, AllocAnyThread}; /// /// extern_class!( /// struct MyClass; /// -/// // SAFETY: The superclass and the mutability is correctly specified. +/// // SAFETY: The superclass is correctly specified, and can be safely +/// // used from any thread. /// unsafe impl ClassType for MyClass { /// type Super = NSObject; -/// type Mutability = mutability::InteriorMutable; /// # // For testing purposes /// # const NAME: &'static str = "NSObject"; /// } @@ -223,11 +218,17 @@ pub unsafe trait ClassType: Message { /// [`AnyObject`]: crate::runtime::AnyObject type Super: Message; - /// Whether the type is mutable or immutable. + /// Whether the type can be used from any thread, or from only the main + /// thread. + /// + /// One of [`dyn AllocAnyThread`] or [`dyn MainThreadOnly`]. + /// + /// Setting this makes `ClassType` provide an implementation of either + /// [`AllocAnyThread`] or [`MainThreadOnly`]. /// - /// See the [`mutability`][crate::mutability] module for further details - /// about class mutability. - type Mutability: Mutability; + /// [`dyn AllocAnyThread`]: AllocAnyThread + /// [`dyn MainThreadOnly`]: MainThreadOnly + type ThreadKind: ?Sized + ThreadKind; /// The name of the Objective-C class that this type represents. /// @@ -250,76 +251,6 @@ pub unsafe trait ClassType: Message { // Note: It'd be safe to provide a default impl using transmute here if // we wanted to! fn as_super(&self) -> &Self::Super; - - /// Allocate a new instance of the class. - /// - /// The return value can be used directly inside [`msg_send_id!`] to - /// initialize the object. - /// - /// For classes that are only usable on the main thread, you can use - /// `MainThreadMarker::alloc` instead. - /// - /// [`msg_send_id!`]: crate::msg_send_id - // - // Note: We could have placed this on `mutability::IsAllocableAnyThread`, - // but `ClassType` is more often already in scope, allowing easier access - // to `T::alloc()`. - #[inline] - fn alloc() -> Allocated - where - Self: IsAllocableAnyThread + Sized, - { - // SAFETY: - // - It is always safe to (attempt to) allocate an object. - // - The object is of the correct type, since we've used the class - // from `Self::class`. - // - The object is safe to `dealloc` on the current thread (due to the - // `IsAllocableAnyThread` bound which guarantees it is not - // `MainThreadOnly`). - // - // See also `MainThreadMarker::alloc`. - unsafe { msg_send_id![Self::class(), alloc] } - } - - /// Allocate a new instance of the class on the main thread. - /// - /// This is essentially the same as [`ClassType::alloc`], the difference - /// being that it is also callable with classes that can only be used on - /// the main thread. - /// - /// - /// # Example - /// - /// Create an object on the main thread. - /// - /// ``` - /// # use objc2::runtime::NSObject as SomeClass; - /// # #[cfg(for_example)] - /// use objc2_app_kit::NSView as SomeClass; // An example class - /// use objc2::rc::Retained; - /// use objc2::{msg_send_id, ClassType, MainThreadMarker}; - /// - /// # let mtm = unsafe { MainThreadMarker::new_unchecked() }; - /// # #[cfg(doctests_not_always_run_on_main_thread)] - /// let mtm = MainThreadMarker::new().expect("must be on the main thread"); - /// - /// // _All_ objects are safe to allocate on the main thread! - /// let obj = SomeClass::alloc_main_thread(mtm); - /// - /// // Though more knowledge is required for safe initialization - /// let obj: Retained = unsafe { msg_send_id![obj, init] }; - /// ``` - #[inline] - fn alloc_main_thread(mtm: MainThreadMarker) -> Allocated - where - Self: Sized, - { - // SAFETY: Same as `ClassType::alloc`, with the addition that since we - // take `mtm: MainThreadMarker`, the `IsAllocableAnyThread` bound is - // not required. - let _ = mtm; - unsafe { msg_send_id![Self::class(), alloc] } - } } /// Marks types whose implementation is defined in Rust. @@ -438,3 +369,205 @@ pub unsafe trait ProtocolType { #[doc(hidden)] const __INNER: (); } + +// Split into separate traits for better diagnostics +mod private { + pub trait SealedAllocAnyThread {} + pub trait SealedMainThreadOnly {} + pub trait SealedThreadKind {} +} + +/// Marker trait for classes (and protocols) that are usable from any thread, +/// i.e. the opposite of [`MainThreadOnly`]. +/// +/// This is mostly an implementation detail to expose the [`alloc`] method +/// with different signatures depending on whether a class is main thread only +/// or not. You can safely assume that things are safe to use from any thread, +/// _unless_ they implement [`MainThreadOnly`], not only if they implement +/// this trait. +/// +/// +/// # Safety +/// +/// This is a sealed trait, and should not need to be implemented; it is +/// implemented automatically when you implement [`ClassType`]. +// +// NOTE: Ideally this would be an auto trait that had a negative impl for +// `MainThreadOnly`, something like: +// +// pub unsafe auto trait AnyThread {} +// pub unsafe trait MainThreadOnly {} +// impl !AnyThread for T {} +// +// This isn't possible in current Rust though, so we'll have to hack it. +pub unsafe trait AllocAnyThread: private::SealedAllocAnyThread { + /// Allocate a new instance of the class. + /// + /// The return value can be used directly inside [`msg_send_id!`] to + /// initialize the object. + /// + /// [`msg_send_id!`]: crate::msg_send_id + #[inline] + fn alloc() -> Allocated + where + Self: Sized + ClassType, + { + // SAFETY: + // - It is always safe to (attempt to) allocate an object. + // - The object is of the correct type, since we've used the class + // from `Self::class`. + // - The object is safe to `dealloc` on the current thread (due to the + // `AnyThread` bound which guarantees it is not `MainThreadOnly`). + // + // While Xcode's Main Thread Checker doesn't report `alloc` and + // `dealloc` as unsafe from other threads, things like `NSView` and + // `NSWindow` still do a non-trivial amount of stuff on `dealloc`, + // even if the object is freshly `alloc`'d - which is why we disallow + // this. + // + // This also has the nice property that `Allocated` is guaranteed + // to be allowed to `init` on the current thread. + // + // See also `MainThreadMarker::alloc`. + unsafe { msg_send_id![Self::class(), alloc] } + } +} + +// The impl here is a bit bad for diagnostics, but required to prevent users +// implementing the trait themselves. +impl<'a, T: ?Sized + ClassType> private::SealedAllocAnyThread + for T +{ +} +unsafe impl<'a, T: ?Sized + ClassType> AllocAnyThread for T {} + +impl private::SealedAllocAnyThread for ProtocolObject

{} +unsafe impl AllocAnyThread for ProtocolObject

{} + +/// Marker trait for classes and protocols that are only safe to use on the +/// main thread. +/// +/// This is commonly used in GUI code like `AppKit` and `UIKit`, e.g. +/// `UIWindow` is only usable from the application's main thread because it +/// accesses global statics like the `UIApplication`. +/// +/// See [`MainThreadMarker`] for a few more details on this. +/// +/// +/// # Safety +/// +/// It is unsound to implement [`Send`] or [`Sync`] together with this. +/// +/// This is a sealed trait, and should not need to be implemented; it is +/// implemented automatically when you implement [`ClassType`]. +#[doc(alias = "@MainActor")] +pub unsafe trait MainThreadOnly: private::SealedMainThreadOnly { + /// Get a [`MainThreadMarker`] from the main-thread-only object. + /// + /// This function exists purely in the type-system, and will succeed at + /// runtime (with a safety check when debug assertions are enabled). + #[inline] + #[cfg_attr(debug_assertions, track_caller)] + fn mtm(&self) -> MainThreadMarker { + #[cfg(debug_assertions)] + assert!( + MainThreadMarker::new().is_some(), + "the main-thread-only object that we tried to fetch a MainThreadMarker from was somehow not on the main thread", + ); + + // SAFETY: Objects which are `MainThreadOnly` are guaranteed + // `!Send + !Sync` and are only constructible on the main thread. + // + // Since we hold `&self`, i.e. a reference to such an object, and we + // know it cannot possibly be on another thread than the main, we know + // that the current thread is the main thread. + unsafe { MainThreadMarker::new_unchecked() } + } + + /// Allocate a new instance of the class on the main thread. + /// + /// + /// # Example + /// + /// Create a view on the main thread. + /// + /// ``` + /// use objc2::{MainThreadOnly, MainThreadMarker}; + /// # #[cfg(available_in_app_kit)] + /// use objc2_app_kit::NSView; + /// use objc2_foundation::CGRect; + /// # + /// # use objc2::ClassType; + /// # use objc2::rc::{Allocated, Retained}; + /// # + /// # objc2::extern_class!( + /// # struct NSView; + /// # + /// # unsafe impl ClassType for NSView { + /// # type Super = objc2::runtime::NSObject; + /// # type ThreadKind = dyn MainThreadOnly; + /// # const NAME: &'static str = "NSObject"; // For example + /// # } + /// # ); + /// # + /// # impl NSView { + /// # fn initWithFrame(this: Allocated, _frame: CGRect) -> Retained { + /// # // Don't use frame, this is NSObject + /// # unsafe { objc2::msg_send_id![this, init] } + /// # } + /// # } + /// + /// # #[cfg(doctests_not_always_run_on_main_thread)] + /// let mtm = MainThreadMarker::new().expect("must be on the main thread"); + /// # let mtm = unsafe { MainThreadMarker::new_unchecked() }; + /// + /// let frame = CGRect::default(); + /// let view = NSView::initWithFrame(NSView::alloc(mtm), frame); + /// ``` + #[inline] + fn alloc(mtm: MainThreadMarker) -> Allocated + where + Self: Sized + ClassType, + { + mtm.alloc() + } +} + +impl<'a, T: ?Sized + ClassType> private::SealedMainThreadOnly + for T +{ +} +unsafe impl<'a, T: ?Sized + ClassType> MainThreadOnly for T {} + +impl private::SealedMainThreadOnly for ProtocolObject

{} +unsafe impl MainThreadOnly for ProtocolObject

{} + +/// The allowed values in [`ClassType::ThreadKind`]. +/// +/// One of [`dyn AllocAnyThread`] or [`dyn MainThreadOnly`]. +/// +/// [`dyn AllocAnyThread`]: AllocAnyThread +/// [`dyn MainThreadOnly`]: MainThreadOnly +pub trait ThreadKind: private::SealedThreadKind { + // To mark `ThreadKind` as not object safe for now. + #[doc(hidden)] + const __NOT_OBJECT_SAFE: (); +} + +impl<'a> private::SealedThreadKind for dyn AllocAnyThread + 'a {} +impl<'a> ThreadKind for dyn AllocAnyThread + 'a { + const __NOT_OBJECT_SAFE: () = (); +} + +impl<'a> private::SealedThreadKind for dyn MainThreadOnly + 'a {} +impl<'a> ThreadKind for dyn MainThreadOnly + 'a { + const __NOT_OBJECT_SAFE: () = (); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[allow(unused)] + fn object_safe(_: &dyn AllocAnyThread, _: &dyn MainThreadOnly) {} +} diff --git a/crates/objc2/src/topics/kvo.md b/crates/objc2/src/topics/kvo.md index 5ecccc48b..6cdbcecd9 100644 --- a/crates/objc2/src/topics/kvo.md +++ b/crates/objc2/src/topics/kvo.md @@ -21,7 +21,7 @@ use core::ptr; use objc2::rc::Retained; use objc2::runtime::AnyObject; -use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, msg_send_id, AllocAnyThread, ClassType, DeclaredClass}; use objc2_foundation::{ ns_string, NSCopying, NSDictionary, NSKeyValueChangeKey, NSKeyValueObservingOptions, NSObject, NSObjectNSKeyValueObserverRegistration, NSObjectProtocol, NSString, @@ -39,13 +39,11 @@ declare_class!( // SAFETY: // - The superclass NSObject does not have any subclassing requirements. - // - Interior mutability is a safe default. // - MyObserver implements `Drop` and ensures that: // - It does not call an overridden method. // - It does not `retain` itself. unsafe impl ClassType for MyObserver { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "MyObserver"; } diff --git a/crates/objc2/src/topics/layered_safety.md b/crates/objc2/src/topics/layered_safety.md index 9f45ba420..308221094 100644 --- a/crates/objc2/src/topics/layered_safety.md +++ b/crates/objc2/src/topics/layered_safety.md @@ -206,7 +206,7 @@ The `NSData` example again. use objc2::ffi::NSUInteger; use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( #[derive(PartialEq, Eq, Hash)] @@ -214,7 +214,6 @@ extern_class!( unsafe impl ClassType for NSData { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/objc2/src/topics/mvc.md b/crates/objc2/src/topics/mvc.md index 757408de5..246c84126 100644 --- a/crates/objc2/src/topics/mvc.md +++ b/crates/objc2/src/topics/mvc.md @@ -6,11 +6,11 @@ The [Model-View-Controller (MVC) design pattern][mvc-doc] is quite prominent in **View**: Use the built-in views (`NSView` or `UIView`). If you need to register a delegate on these, use the controller as the delegate. -**Controller**: Use the [`declare_class!`] macro to create a new object. Use [`mutability::MainThreadOnly`] as the [`ClassType::Mutability`], so that you can implement view delegate protocols. +**Controller**: Use the [`declare_class!`] macro to create a new object. Use [`MainThreadOnly`] as the [`ClassType::ThreadKind`], so that you can implement view delegate protocols. [mvc-doc]: https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/Model-View-Controller/Model-View-Controller.html [`Cell`]: core::cell::Cell [`RefCell`]: core::cell::RefCell [`declare_class!`]: crate::declare_class -[`mutability::MainThreadOnly`]: crate::mutability::MainThreadOnly -[`ClassType::Mutability`]: crate::ClassType::Mutability +[`MainThreadOnly`]: crate::MainThreadOnly +[`ClassType::ThreadKind`]: crate::ClassType::ThreadKind diff --git a/crates/objc2/tests/declare_class.rs b/crates/objc2/tests/declare_class.rs index 1f99dd3d2..742c7a90e 100644 --- a/crates/objc2/tests/declare_class.rs +++ b/crates/objc2/tests/declare_class.rs @@ -1,7 +1,6 @@ #![deny(deprecated, unreachable_code)] use core::ptr::{self, NonNull}; -use objc2::mutability::InteriorMutable; use objc2::rc::Retained; use objc2::runtime::NSObject; use objc2::{declare_class, extern_methods, sel, ClassType, DeclaredClass}; @@ -13,7 +12,6 @@ declare_class!( unsafe impl ClassType for DeclareClassDepreactedMethod { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "DeclareClassDepreactedMethod"; } @@ -46,7 +44,6 @@ declare_class!( unsafe impl ClassType for DeclareClassCfg { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "DeclareClassCfg"; } @@ -190,7 +187,6 @@ declare_class!( unsafe impl ClassType for TestMultipleColonSelector { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestMultipleColonSelector"; } @@ -265,7 +261,6 @@ declare_class!( unsafe impl ClassType for DeclareClassAllTheBool { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "DeclareClassAllTheBool"; } @@ -330,7 +325,6 @@ declare_class!( unsafe impl ClassType for DeclareClassUnreachable { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "DeclareClassUnreachable"; } @@ -381,7 +375,6 @@ declare_class!( unsafe impl ClassType for OutParam { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "OutParam"; } @@ -459,7 +452,6 @@ fn test_pointer_receiver_allowed() { unsafe impl ClassType for PointerReceiver { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "PointerReceiver"; } diff --git a/crates/objc2/tests/declare_class_self.rs b/crates/objc2/tests/declare_class_self.rs index f9a1b24e2..928ca648f 100644 --- a/crates/objc2/tests/declare_class_self.rs +++ b/crates/objc2/tests/declare_class_self.rs @@ -3,7 +3,7 @@ //! do it in a context where `Self` works. use objc2::rc::{Allocated, Retained}; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, ClassType, DeclaredClass}; trait GetSameType { type SameType: ?Sized; @@ -32,8 +32,6 @@ declare_class!( unsafe impl ClassType for MyTestObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; - const NAME: &'static str = "MyTestObject"; } diff --git a/crates/objc2/tests/macros_mainthreadmarker.rs b/crates/objc2/tests/macros_mainthreadmarker.rs index 60aed1af2..b9274e0b5 100644 --- a/crates/objc2/tests/macros_mainthreadmarker.rs +++ b/crates/objc2/tests/macros_mainthreadmarker.rs @@ -1,8 +1,7 @@ use objc2::rc::Retained; use objc2::runtime::{NSObject, NSObjectProtocol}; use objc2::{ - declare_class, extern_methods, extern_protocol, mutability, ClassType, DeclaredClass, - ProtocolType, + declare_class, extern_methods, extern_protocol, ClassType, DeclaredClass, ProtocolType, }; extern_protocol!( @@ -26,7 +25,6 @@ declare_class!( unsafe impl ClassType for Cls { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "MainThreadMarkerTest"; } diff --git a/crates/objc2/tests/no_prelude.rs b/crates/objc2/tests/no_prelude.rs index 855a3101e..36f2b36b7 100644 --- a/crates/objc2/tests/no_prelude.rs +++ b/crates/objc2/tests/no_prelude.rs @@ -95,7 +95,6 @@ new_objc2::declare_class!( unsafe impl ClassType for CustomObject { type Super = new_objc2::runtime::NSObject; - type Mutability = new_objc2::mutability::InteriorMutable; const NAME: &'static str = "CustomObject"; } @@ -134,7 +133,6 @@ new_objc2::extern_class!( unsafe impl ClassType for NSObject2 { type Super = new_objc2::runtime::NSObject; - type Mutability = new_objc2::mutability::InteriorMutable; const NAME: &'static str = "NSObject"; } ); diff --git a/crates/objc2/tests/track_caller.rs b/crates/objc2/tests/track_caller.rs index 6bffe2522..678f3d3f2 100644 --- a/crates/objc2/tests/track_caller.rs +++ b/crates/objc2/tests/track_caller.rs @@ -14,7 +14,7 @@ use std::sync::Mutex; use objc2::encode::Encode; use objc2::rc::{self, Allocated, Retained}; use objc2::runtime::{self, NSObject}; -use objc2::{class, declare_class, msg_send, msg_send_id, mutability, ClassType, DeclaredClass}; +use objc2::{class, declare_class, msg_send, msg_send_id, ClassType, DeclaredClass}; #[path = "../src/rc/test_object.rs"] #[allow(dead_code)] @@ -208,7 +208,6 @@ declare_class!( unsafe impl ClassType for PanickingClass { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "PanickingClass"; } diff --git a/crates/objc2/tests/use_macros.rs b/crates/objc2/tests/use_macros.rs index 3e9a6073f..a70fa7baa 100644 --- a/crates/objc2/tests/use_macros.rs +++ b/crates/objc2/tests/use_macros.rs @@ -1,4 +1,3 @@ -use objc2::mutability::InteriorMutable; use objc2::runtime::{AnyClass, NSObject}; use objc2::{class, declare_class, msg_send, sel, ClassType, DeclaredClass}; @@ -7,7 +6,6 @@ declare_class!( unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "MyObject"; } diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s index c123fd4f5..b5325e7db 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-aarch64.s @@ -73,9 +73,9 @@ Lloh11: cbz x0, LBB1_8 str x0, [sp, #8] Lloh12: - adrp x8, L_OBJC_SELECTOR_REFERENCES_5fb5787f6f0227be@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_518803e84ea38a73@PAGE Lloh13: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_5fb5787f6f0227be@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_518803e84ea38a73@PAGEOFF] Lloh14: adrp x4, l_anon.[ID].16@PAGE Lloh15: @@ -89,9 +89,9 @@ Lloh17: mov x3, #0 bl SYM(objc2::runtime::declare::ClassBuilder::add_class_method_inner::GENERATED_ID, 0) Lloh18: - adrp x8, L_OBJC_SELECTOR_REFERENCES_37797af088d7ed2c@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_05fa1b2ffc15d267@PAGE Lloh19: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_37797af088d7ed2c@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_05fa1b2ffc15d267@PAGEOFF] Lloh20: adrp x4, l_anon.[ID].3@PAGE Lloh21: @@ -105,9 +105,9 @@ Lloh23: mov x3, #0 bl SYM(objc2::runtime::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) Lloh24: - adrp x8, L_OBJC_SELECTOR_REFERENCES_6707d96371f346cd@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_58736195c9ca7c7f@PAGE Lloh25: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_6707d96371f346cd@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_58736195c9ca7c7f@PAGEOFF] Lloh26: adrp x19, l_anon.[ID].17@PAGE Lloh27: @@ -122,9 +122,9 @@ Lloh29: mov x4, x19 bl SYM(objc2::runtime::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) Lloh30: - adrp x8, L_OBJC_SELECTOR_REFERENCES_d1f0a69271fa8a42@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_61b74dbf9c375668@PAGE Lloh31: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_d1f0a69271fa8a42@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_61b74dbf9c375668@PAGEOFF] Lloh32: adrp x20, l_anon.[ID].18@PAGE Lloh33: @@ -139,9 +139,9 @@ Lloh35: mov x4, x20 bl SYM(objc2::runtime::declare::ClassBuilder::add_method_inner::GENERATED_ID, 0) Lloh36: - adrp x8, L_OBJC_SELECTOR_REFERENCES_6b5f093807011d2d@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_96586542870e42e5@PAGE Lloh37: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_6b5f093807011d2d@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_96586542870e42e5@PAGEOFF] Lloh38: adrp x5, _method_id_with_param@PAGE Lloh39: @@ -174,9 +174,9 @@ Lloh43: bl _class_addProtocol LBB1_6: Lloh44: - adrp x8, L_OBJC_SELECTOR_REFERENCES_011234c2c0a83075@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_f4e71677dafa88a8@PAGE Lloh45: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_011234c2c0a83075@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_f4e71677dafa88a8@PAGEOFF] Lloh46: adrp x2, l_anon.[ID].23@PAGE Lloh47: @@ -1020,9 +1020,9 @@ LBB20_2: stp x29, x30, [sp, #16] add x29, sp, #16 Lloh212: - adrp x8, L_OBJC_SELECTOR_REFERENCES_23e38d84f82d44df@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_7f51a873b0d59f00@PAGE Lloh213: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_23e38d84f82d44df@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_7f51a873b0d59f00@PAGEOFF] Lloh214: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE Lloh215: @@ -1124,9 +1124,9 @@ LBB22_2: bl _objc_release LBB22_3: Lloh231: - adrp x8, L_OBJC_SELECTOR_REFERENCES_37e98596ca019dd1@PAGE + adrp x8, L_OBJC_SELECTOR_REFERENCES_802cb9c5fa0b19dd@PAGE Lloh232: - ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_37e98596ca019dd1@PAGEOFF] + ldr x1, [x8, L_OBJC_SELECTOR_REFERENCES_802cb9c5fa0b19dd@PAGEOFF] Lloh233: adrp x8, L_OBJC_CLASSLIST_REFERENCES_$_NSObject@GOTPAGE Lloh234: @@ -1274,105 +1274,105 @@ l_anon.[ID].23: .space 24 .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_5fb5787f6f0227be -L_OBJC_METH_VAR_NAME_5fb5787f6f0227be: + .globl L_OBJC_METH_VAR_NAME_518803e84ea38a73 +L_OBJC_METH_VAR_NAME_518803e84ea38a73: .asciz "classMethod" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_5fb5787f6f0227be + .globl L_OBJC_SELECTOR_REFERENCES_518803e84ea38a73 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_5fb5787f6f0227be: - .quad L_OBJC_METH_VAR_NAME_5fb5787f6f0227be +L_OBJC_SELECTOR_REFERENCES_518803e84ea38a73: + .quad L_OBJC_METH_VAR_NAME_518803e84ea38a73 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_5fb5787f6f0227be + .globl L_OBJC_IMAGE_INFO_518803e84ea38a73 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_5fb5787f6f0227be: +L_OBJC_IMAGE_INFO_518803e84ea38a73: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_37797af088d7ed2c -L_OBJC_METH_VAR_NAME_37797af088d7ed2c: + .globl L_OBJC_METH_VAR_NAME_05fa1b2ffc15d267 +L_OBJC_METH_VAR_NAME_05fa1b2ffc15d267: .asciz "method" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_37797af088d7ed2c + .globl L_OBJC_SELECTOR_REFERENCES_05fa1b2ffc15d267 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_37797af088d7ed2c: - .quad L_OBJC_METH_VAR_NAME_37797af088d7ed2c +L_OBJC_SELECTOR_REFERENCES_05fa1b2ffc15d267: + .quad L_OBJC_METH_VAR_NAME_05fa1b2ffc15d267 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_37797af088d7ed2c + .globl L_OBJC_IMAGE_INFO_05fa1b2ffc15d267 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_37797af088d7ed2c: +L_OBJC_IMAGE_INFO_05fa1b2ffc15d267: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6707d96371f346cd -L_OBJC_METH_VAR_NAME_6707d96371f346cd: + .globl L_OBJC_METH_VAR_NAME_58736195c9ca7c7f +L_OBJC_METH_VAR_NAME_58736195c9ca7c7f: .asciz "methodBool:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6707d96371f346cd + .globl L_OBJC_SELECTOR_REFERENCES_58736195c9ca7c7f .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_6707d96371f346cd: - .quad L_OBJC_METH_VAR_NAME_6707d96371f346cd +L_OBJC_SELECTOR_REFERENCES_58736195c9ca7c7f: + .quad L_OBJC_METH_VAR_NAME_58736195c9ca7c7f .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_6707d96371f346cd + .globl L_OBJC_IMAGE_INFO_58736195c9ca7c7f .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6707d96371f346cd: +L_OBJC_IMAGE_INFO_58736195c9ca7c7f: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_d1f0a69271fa8a42 -L_OBJC_METH_VAR_NAME_d1f0a69271fa8a42: + .globl L_OBJC_METH_VAR_NAME_61b74dbf9c375668 +L_OBJC_METH_VAR_NAME_61b74dbf9c375668: .asciz "methodId" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_d1f0a69271fa8a42 + .globl L_OBJC_SELECTOR_REFERENCES_61b74dbf9c375668 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_d1f0a69271fa8a42: - .quad L_OBJC_METH_VAR_NAME_d1f0a69271fa8a42 +L_OBJC_SELECTOR_REFERENCES_61b74dbf9c375668: + .quad L_OBJC_METH_VAR_NAME_61b74dbf9c375668 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_d1f0a69271fa8a42 + .globl L_OBJC_IMAGE_INFO_61b74dbf9c375668 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_d1f0a69271fa8a42: +L_OBJC_IMAGE_INFO_61b74dbf9c375668: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_6b5f093807011d2d -L_OBJC_METH_VAR_NAME_6b5f093807011d2d: + .globl L_OBJC_METH_VAR_NAME_96586542870e42e5 +L_OBJC_METH_VAR_NAME_96586542870e42e5: .asciz "methodIdWithParam:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_6b5f093807011d2d + .globl L_OBJC_SELECTOR_REFERENCES_96586542870e42e5 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_6b5f093807011d2d: - .quad L_OBJC_METH_VAR_NAME_6b5f093807011d2d +L_OBJC_SELECTOR_REFERENCES_96586542870e42e5: + .quad L_OBJC_METH_VAR_NAME_96586542870e42e5 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_6b5f093807011d2d + .globl L_OBJC_IMAGE_INFO_96586542870e42e5 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_6b5f093807011d2d: +L_OBJC_IMAGE_INFO_96586542870e42e5: .asciz "\000\000\000\000@\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_011234c2c0a83075 -L_OBJC_METH_VAR_NAME_011234c2c0a83075: + .globl L_OBJC_METH_VAR_NAME_f4e71677dafa88a8 +L_OBJC_METH_VAR_NAME_f4e71677dafa88a8: .asciz "copyWithZone:" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_011234c2c0a83075 + .globl L_OBJC_SELECTOR_REFERENCES_f4e71677dafa88a8 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_011234c2c0a83075: - .quad L_OBJC_METH_VAR_NAME_011234c2c0a83075 +L_OBJC_SELECTOR_REFERENCES_f4e71677dafa88a8: + .quad L_OBJC_METH_VAR_NAME_f4e71677dafa88a8 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_011234c2c0a83075 + .globl L_OBJC_IMAGE_INFO_f4e71677dafa88a8 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_011234c2c0a83075: +L_OBJC_IMAGE_INFO_f4e71677dafa88a8: .asciz "\000\000\000\000@\000\000" .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 1) @@ -1383,23 +1383,23 @@ L_OBJC_IMAGE_INFO_011234c2c0a83075: .p2align 3, 0x0 l_anon.[ID].24: .quad l_anon.[ID].14 - .asciz "5\000\000\000\000\000\000\000S\000\000\000\001\000\000" + .asciz "5\000\000\000\000\000\000\000R\000\000\000\001\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_23e38d84f82d44df -L_OBJC_METH_VAR_NAME_23e38d84f82d44df: + .globl L_OBJC_METH_VAR_NAME_7f51a873b0d59f00 +L_OBJC_METH_VAR_NAME_7f51a873b0d59f00: .asciz "init" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_23e38d84f82d44df + .globl L_OBJC_SELECTOR_REFERENCES_7f51a873b0d59f00 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_23e38d84f82d44df: - .quad L_OBJC_METH_VAR_NAME_23e38d84f82d44df +L_OBJC_SELECTOR_REFERENCES_7f51a873b0d59f00: + .quad L_OBJC_METH_VAR_NAME_7f51a873b0d59f00 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_23e38d84f82d44df + .globl L_OBJC_IMAGE_INFO_7f51a873b0d59f00 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_23e38d84f82d44df: +L_OBJC_IMAGE_INFO_7f51a873b0d59f00: .asciz "\000\000\000\000@\000\000" .globl SYM(test_declare_class[CRATE_ID]::_::__OBJC2_IVAR_OFFSET, 0) @@ -1410,23 +1410,23 @@ L_OBJC_IMAGE_INFO_23e38d84f82d44df: .p2align 3, 0x0 l_anon.[ID].25: .quad l_anon.[ID].14 - .asciz "5\000\000\000\000\000\000\000|\000\000\000\001\000\000" + .asciz "5\000\000\000\000\000\000\000z\000\000\000\001\000\000" .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_37e98596ca019dd1 -L_OBJC_METH_VAR_NAME_37e98596ca019dd1: + .globl L_OBJC_METH_VAR_NAME_802cb9c5fa0b19dd +L_OBJC_METH_VAR_NAME_802cb9c5fa0b19dd: .asciz "init" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_37e98596ca019dd1 + .globl L_OBJC_SELECTOR_REFERENCES_802cb9c5fa0b19dd .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_37e98596ca019dd1: - .quad L_OBJC_METH_VAR_NAME_37e98596ca019dd1 +L_OBJC_SELECTOR_REFERENCES_802cb9c5fa0b19dd: + .quad L_OBJC_METH_VAR_NAME_802cb9c5fa0b19dd .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_37e98596ca019dd1 + .globl L_OBJC_IMAGE_INFO_802cb9c5fa0b19dd .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_37e98596ca019dd1: +L_OBJC_IMAGE_INFO_802cb9c5fa0b19dd: .asciz "\000\000\000\000@\000\000" .zerofill __DATA,__bss,__MergedGlobals,48,3 diff --git a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s index 2c4337415..89b983e49 100644 --- a/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s +++ b/crates/test-assembly/crates/test_declare_class/expected/apple-x86_64.s @@ -61,7 +61,7 @@ SYM(::call_once::<::call_once::<::call_once::<::call_once::<::class::REGISTER_CLASS, 0),8,3 .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_23e38d84f82d44df -L_OBJC_METH_VAR_NAME_23e38d84f82d44df: + .globl L_OBJC_METH_VAR_NAME_7f51a873b0d59f00 +L_OBJC_METH_VAR_NAME_7f51a873b0d59f00: .asciz "init" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_23e38d84f82d44df + .globl L_OBJC_SELECTOR_REFERENCES_7f51a873b0d59f00 .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_23e38d84f82d44df: - .quad L_OBJC_METH_VAR_NAME_23e38d84f82d44df +L_OBJC_SELECTOR_REFERENCES_7f51a873b0d59f00: + .quad L_OBJC_METH_VAR_NAME_7f51a873b0d59f00 .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_23e38d84f82d44df + .globl L_OBJC_IMAGE_INFO_7f51a873b0d59f00 .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_23e38d84f82d44df: +L_OBJC_IMAGE_INFO_7f51a873b0d59f00: .asciz "\000\000\000\000@\000\000" .zerofill __DATA,__bss,SYM(test_declare_class[CRATE_ID]::_::__OBJC2_CLASS, 1).0,8,3 @@ -977,24 +977,24 @@ L_OBJC_IMAGE_INFO_23e38d84f82d44df: .p2align 3, 0x0 l_anon.[ID].25: .quad l_anon.[ID].14 - .asciz "5\000\000\000\000\000\000\000|\000\000\000\001\000\000" + .asciz "5\000\000\000\000\000\000\000z\000\000\000\001\000\000" .zerofill __DATA,__bss,SYM(::class::REGISTER_CLASS, 0),8,3 .section __TEXT,__objc_methname,cstring_literals - .globl L_OBJC_METH_VAR_NAME_37e98596ca019dd1 -L_OBJC_METH_VAR_NAME_37e98596ca019dd1: + .globl L_OBJC_METH_VAR_NAME_802cb9c5fa0b19dd +L_OBJC_METH_VAR_NAME_802cb9c5fa0b19dd: .asciz "init" .section __DATA,__objc_selrefs,literal_pointers,no_dead_strip - .globl L_OBJC_SELECTOR_REFERENCES_37e98596ca019dd1 + .globl L_OBJC_SELECTOR_REFERENCES_802cb9c5fa0b19dd .p2align 3, 0x0 -L_OBJC_SELECTOR_REFERENCES_37e98596ca019dd1: - .quad L_OBJC_METH_VAR_NAME_37e98596ca019dd1 +L_OBJC_SELECTOR_REFERENCES_802cb9c5fa0b19dd: + .quad L_OBJC_METH_VAR_NAME_802cb9c5fa0b19dd .section __DATA,__objc_imageinfo,regular,no_dead_strip - .globl L_OBJC_IMAGE_INFO_37e98596ca019dd1 + .globl L_OBJC_IMAGE_INFO_802cb9c5fa0b19dd .p2align 2, 0x0 -L_OBJC_IMAGE_INFO_37e98596ca019dd1: +L_OBJC_IMAGE_INFO_802cb9c5fa0b19dd: .asciz "\000\000\000\000@\000\000" .subsections_via_symbols diff --git a/crates/test-assembly/crates/test_declare_class/lib.rs b/crates/test-assembly/crates/test_declare_class/lib.rs index 1e25381df..c8cf50573 100644 --- a/crates/test-assembly/crates/test_declare_class/lib.rs +++ b/crates/test-assembly/crates/test_declare_class/lib.rs @@ -8,7 +8,7 @@ use core::ptr; use objc2::rc::{Allocated, Retained}; use objc2::runtime::AnyClass; -use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, msg_send_id, ClassType, DeclaredClass}; use objc2_foundation::{CopyingHelper, NSCopying, NSObject, NSObjectProtocol, NSZone}; declare_class!( @@ -17,7 +17,6 @@ declare_class!( unsafe impl ClassType for NoIvars { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "NoIvars"; } @@ -86,7 +85,6 @@ declare_class!( unsafe impl ClassType for ForgetableIvars { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "ForgetableIvars"; } @@ -127,7 +125,6 @@ declare_class!( unsafe impl ClassType for DropIvars { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "DropIvars"; } diff --git a/crates/test-fuzz/fuzz_targets/collection_interior_mut.rs b/crates/test-fuzz/fuzz_targets/collection_interior_mut.rs index a0cc9376e..6216232d0 100644 --- a/crates/test-fuzz/fuzz_targets/collection_interior_mut.rs +++ b/crates/test-fuzz/fuzz_targets/collection_interior_mut.rs @@ -12,7 +12,7 @@ use std::hint::black_box; use arbitrary::Arbitrary; use objc2::rc::{autoreleasepool, Id, Retained}; use objc2::runtime::AnyObject; -use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass, Message}; +use objc2::{declare_class, msg_send_id, AllocAnyThread, ClassType, DeclaredClass, Message}; use objc2_foundation::{ CopyingHelper, NSCopying, NSMutableDictionary, NSMutableSet, NSObject, NSObjectProtocol, NSUInteger, NSZone, @@ -52,7 +52,6 @@ declare_class!( unsafe impl ClassType for Key { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "Key"; } diff --git a/crates/test-ui/ui/declare_class_classtype_imported.rs b/crates/test-ui/ui/declare_class_classtype_imported.rs index 6fc85f270..7a82a2511 100644 --- a/crates/test-ui/ui/declare_class_classtype_imported.rs +++ b/crates/test-ui/ui/declare_class_classtype_imported.rs @@ -1,13 +1,12 @@ #![allow(unused_imports)] +use objc2::declare_class; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability}; declare_class!( struct CustomObject; unsafe impl objc2::ClassType for CustomObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject"; } diff --git a/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.rs b/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.rs index 20af6c988..0707fe667 100644 --- a/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.rs +++ b/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.rs @@ -1,16 +1,15 @@ //! Test that implementing `NSApplicationDelegate` and similar requires //! a `MainThreadOnly` class. -use objc2::mutability::IsMainThreadOnly; use objc2::rc::Retained; use objc2::{ - declare_class, extern_methods, extern_protocol, mutability, ClassType, DeclaredClass, - ProtocolType, + declare_class, extern_methods, extern_protocol, AllocAnyThread, ClassType, DeclaredClass, + MainThreadOnly, ProtocolType, }; use objc2_foundation::{MainThreadMarker, NSNotification, NSObject, NSObjectProtocol}; // Use fake `NSApplicationDelegate` so that this works on iOS too. extern_protocol!( - pub unsafe trait NSApplicationDelegate: NSObjectProtocol + IsMainThreadOnly { + pub unsafe trait NSApplicationDelegate: NSObjectProtocol + MainThreadOnly { #[optional] #[method(applicationDidFinishLaunching:)] unsafe fn applicationDidFinishLaunching(&self, notification: &NSNotification); @@ -26,7 +25,7 @@ declare_class!( unsafe impl ClassType for CustomObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; // Not `MainThreadOnly` + type ThreadKind = dyn AllocAnyThread; // Not `MainThreadOnly` const NAME: &'static str = "CustomObject"; } diff --git a/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.stderr b/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.stderr index 3c233581a..c413bdfd3 100644 --- a/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.stderr +++ b/crates/test-ui/ui/declare_class_delegate_not_mainthreadonly.stderr @@ -1,16 +1,18 @@ -error[E0277]: the trait bound `InteriorMutable: mutability::MutabilityIsMainThreadOnly` is not satisfied +error[E0271]: type mismatch resolving `::ThreadKind == dyn MainThreadOnly` --> ui/declare_class_delegate_not_mainthreadonly.rs | | unsafe impl NSApplicationDelegate for CustomObject { - | ^^^^^^^^^^^^ the trait `mutability::MutabilityIsMainThreadOnly` is not implemented for `InteriorMutable`, which is required by `CustomObject: IsMainThreadOnly` + | ^^^^^^^^^^^^ expected trait `MainThreadOnly`, found trait `AllocAnyThread` | - = help: the trait `mutability::MutabilityIsMainThreadOnly` is implemented for `MainThreadOnly` - = note: required for `CustomObject` to implement `IsMainThreadOnly` + = note: expected trait object `dyn MainThreadOnly` + found trait object `(dyn AllocAnyThread + 'static)` + = help: `(dyn AllocAnyThread + 'static)` implements `MainThreadOnly` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + = note: required for `CustomObject` to implement `MainThreadOnly` note: required by a bound in `NSApplicationDelegate` --> ui/declare_class_delegate_not_mainthreadonly.rs | | / extern_protocol!( - | | pub unsafe trait NSApplicationDelegate: NSObjectProtocol + IsMainThreadOnly { + | | pub unsafe trait NSApplicationDelegate: NSObjectProtocol + MainThreadOnly { | | --------------------- required by a bound in this trait | | #[optional] | | #[method(applicationDidFinishLaunching:)] diff --git a/crates/test-ui/ui/declare_class_invalid_receiver.rs b/crates/test-ui/ui/declare_class_invalid_receiver.rs index fd2703da9..8688d9b23 100644 --- a/crates/test-ui/ui/declare_class_invalid_receiver.rs +++ b/crates/test-ui/ui/declare_class_invalid_receiver.rs @@ -1,14 +1,13 @@ #![allow(unused_variables)] use objc2::rc::{Allocated, Retained}; use objc2::runtime::{AnyClass, NSObject}; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, ClassType, DeclaredClass}; declare_class!( struct CustomObject; unsafe impl ClassType for CustomObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject"; } diff --git a/crates/test-ui/ui/declare_class_invalid_syntax.rs b/crates/test-ui/ui/declare_class_invalid_syntax.rs index 6a1494dfc..1f3daba77 100644 --- a/crates/test-ui/ui/declare_class_invalid_syntax.rs +++ b/crates/test-ui/ui/declare_class_invalid_syntax.rs @@ -1,13 +1,12 @@ use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, ClassType, DeclaredClass}; declare_class!( struct InvalidMethodDeclarations; unsafe impl ClassType for InvalidMethodDeclarations { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "InvalidMethodDeclarations"; } @@ -137,28 +136,16 @@ declare_class!( unsafe impl ClassType for MissingName { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } impl DeclaredClass for MissingName {} ); -declare_class!( - struct MissingMutability; - - unsafe impl ClassType for MissingMutability { - type Super = NSObject; - } - - impl DeclaredClass for MissingMutability {} -); - declare_class!( struct MissingDeclaredClass; unsafe impl ClassType for MissingDeclaredClass { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "MissingDeclaredClass"; } ); diff --git a/crates/test-ui/ui/declare_class_invalid_syntax.stderr b/crates/test-ui/ui/declare_class_invalid_syntax.stderr index f2589da7c..1ffe9ad83 100644 --- a/crates/test-ui/ui/declare_class_invalid_syntax.stderr +++ b/crates/test-ui/ui/declare_class_invalid_syntax.stderr @@ -110,7 +110,7 @@ error: missing parameters for function definition | help: add a parameter list | -72 | fn fn() test_fn_fn() {} +71 | fn fn() test_fn_fn() {} | ++ error: expected one of `->`, `<`, `where`, or `{`, found `test_fn_fn` @@ -462,18 +462,6 @@ note: while trying to match `const` | const NAME: &'static str = $name_const:expr; | ^^^^^ -error: no rules expected the token `}` - --> ui/declare_class_invalid_syntax.rs - | - | } - | ^ no rules expected this token in macro call - | -note: while trying to match `type` - --> $WORKSPACE/crates/objc2/src/macros/declare_class.rs - | - | type Mutability = $mutability:ty; - | ^^^^ - error: unexpected end of macro invocation --> ui/declare_class_invalid_syntax.rs | diff --git a/crates/test-ui/ui/declare_class_invalid_type.rs b/crates/test-ui/ui/declare_class_invalid_type.rs index a50689c59..0399ddb46 100644 --- a/crates/test-ui/ui/declare_class_invalid_type.rs +++ b/crates/test-ui/ui/declare_class_invalid_type.rs @@ -1,13 +1,12 @@ use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, ClassType, DeclaredClass}; declare_class!( struct CustomObject; unsafe impl ClassType for CustomObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject"; } diff --git a/crates/test-ui/ui/declare_class_invalid_type2.rs b/crates/test-ui/ui/declare_class_invalid_type2.rs index f38a6898f..ab14908e8 100644 --- a/crates/test-ui/ui/declare_class_invalid_type2.rs +++ b/crates/test-ui/ui/declare_class_invalid_type2.rs @@ -1,13 +1,12 @@ use objc2::rc::{Allocated, Retained}; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, ClassType, DeclaredClass}; declare_class!( struct CustomObject; unsafe impl ClassType for CustomObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject"; } diff --git a/crates/test-ui/ui/declare_class_mut_self_not_mutable.rs b/crates/test-ui/ui/declare_class_mut_self_not_mutable.rs index 6574936cb..93b7bf547 100644 --- a/crates/test-ui/ui/declare_class_mut_self_not_mutable.rs +++ b/crates/test-ui/ui/declare_class_mut_self_not_mutable.rs @@ -1,13 +1,12 @@ use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, ClassType, DeclaredClass}; declare_class!( struct CustomObject; unsafe impl ClassType for CustomObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject"; } diff --git a/crates/test-ui/ui/extern_class_feature_flag.rs b/crates/test-ui/ui/extern_class_feature_flag.rs index b45869fc8..115c6fa74 100644 --- a/crates/test-ui/ui/extern_class_feature_flag.rs +++ b/crates/test-ui/ui/extern_class_feature_flag.rs @@ -1,5 +1,5 @@ use objc2::runtime::NSObject; -use objc2::{extern_class, mutability, ClassType}; +use objc2::{extern_class, ClassType}; extern_class!( #[cfg(not(test))] @@ -8,7 +8,6 @@ extern_class!( #[cfg(not(test))] unsafe impl ClassType for MyTestEnabled { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); @@ -19,7 +18,6 @@ extern_class!( #[cfg(test)] unsafe impl ClassType for MyTestDisabled { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_class_not_zst.rs b/crates/test-ui/ui/extern_class_not_zst.rs index 37d68a242..aff98c9f5 100644 --- a/crates/test-ui/ui/extern_class_not_zst.rs +++ b/crates/test-ui/ui/extern_class_not_zst.rs @@ -1,5 +1,5 @@ use objc2::runtime::NSObject; -use objc2::{extern_class, mutability, ClassType}; +use objc2::{extern_class, ClassType}; extern_class!( pub struct NSNumber { @@ -8,7 +8,6 @@ extern_class!( unsafe impl ClassType for NSNumber { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_class_root.rs b/crates/test-ui/ui/extern_class_root.rs index d227a3f86..178c565c2 100644 --- a/crates/test-ui/ui/extern_class_root.rs +++ b/crates/test-ui/ui/extern_class_root.rs @@ -2,7 +2,7 @@ use core::ops::Deref; use objc2::encode::{Encoding, RefEncode}; use objc2::runtime::AnyObject; -use objc2::{extern_class, mutability, ClassType, Message}; +use objc2::{extern_class, AllocAnyThread, ClassType, Message}; #[repr(transparent)] struct MyObject(AnyObject); @@ -26,7 +26,7 @@ extern_class!( unsafe impl ClassType for MyRootClass { type Super = MyObject; - type Mutability = mutability::InteriorMutable; + type ThreadKind = dyn AllocAnyThread; } ); diff --git a/crates/test-ui/ui/extern_class_root.stderr b/crates/test-ui/ui/extern_class_root.stderr index 194a566e1..8ea3fcc08 100644 --- a/crates/test-ui/ui/extern_class_root.stderr +++ b/crates/test-ui/ui/extern_class_root.stderr @@ -14,4 +14,12 @@ error[E0277]: the trait bound `MyObject: ClassType` is not satisfied MyRootClass NSObject __NSProxy +note: required by a bound in `ValidThreadKind::check` + --> $WORKSPACE/crates/objc2/src/__macro_helpers/class.rs + | + | Self::Super: ClassType, + | ^^^^^^^^^ required by this bound in `ValidThreadKind::check` +... + | fn check() {} + | ----- required by a bound in this associated function = note: this error originates in the macro `$crate::__inner_extern_class` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/extern_class_subclass_object.rs b/crates/test-ui/ui/extern_class_subclass_object.rs index 164e3e8cf..bf6c5aed1 100644 --- a/crates/test-ui/ui/extern_class_subclass_object.rs +++ b/crates/test-ui/ui/extern_class_subclass_object.rs @@ -1,12 +1,12 @@ use objc2::runtime::AnyObject; -use objc2::{extern_class, mutability, ClassType}; +use objc2::{extern_class, AllocAnyThread, ClassType}; extern_class!( pub struct MyRootClass; unsafe impl ClassType for MyRootClass { type Super = AnyObject; - type Mutability = mutability::InteriorMutable; + type ThreadKind = dyn AllocAnyThread; } ); diff --git a/crates/test-ui/ui/extern_class_subclass_object.stderr b/crates/test-ui/ui/extern_class_subclass_object.stderr index 2f15956d9..6c99faa01 100644 --- a/crates/test-ui/ui/extern_class_subclass_object.stderr +++ b/crates/test-ui/ui/extern_class_subclass_object.stderr @@ -48,4 +48,12 @@ error[E0277]: the trait bound `AnyObject: ClassType` is not satisfied MyRootClass NSObject __NSProxy +note: required by a bound in `ValidThreadKind::check` + --> $WORKSPACE/crates/objc2/src/__macro_helpers/class.rs + | + | Self::Super: ClassType, + | ^^^^^^^^^ required by this bound in `ValidThreadKind::check` +... + | fn check() {} + | ----- required by a bound in this associated function = note: this error originates in the macro `$crate::__inner_extern_class` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/extern_class_thread_kind_invalid.rs b/crates/test-ui/ui/extern_class_thread_kind_invalid.rs new file mode 100644 index 000000000..6efe6912f --- /dev/null +++ b/crates/test-ui/ui/extern_class_thread_kind_invalid.rs @@ -0,0 +1,13 @@ +use objc2::runtime::NSObject; +use objc2::{extern_class, ClassType, ThreadKind}; + +extern_class!( + struct BogusThreadKind; + + unsafe impl ClassType for BogusThreadKind { + type Super = NSObject; + type ThreadKind = dyn ThreadKind; + } +); + +fn main() {} diff --git a/crates/test-ui/ui/extern_class_thread_kind_invalid.stderr b/crates/test-ui/ui/extern_class_thread_kind_invalid.stderr new file mode 100644 index 000000000..fa99140ae --- /dev/null +++ b/crates/test-ui/ui/extern_class_thread_kind_invalid.stderr @@ -0,0 +1,44 @@ +error[E0038]: the trait `ThreadKind` cannot be made into an object + --> ui/extern_class_thread_kind_invalid.rs + | + | type ThreadKind = dyn ThreadKind; + | ^^^^^^^^^^^^^^ `ThreadKind` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $WORKSPACE/crates/objc2/src/top_level_traits.rs + | + | const __NOT_OBJECT_SAFE: (); + | ^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because it contains this associated `const` + +error[E0277]: the trait bound `BogusThreadKind: ValidThreadKind<(dyn ThreadKind + 'static)>` is not satisfied + --> ui/extern_class_thread_kind_invalid.rs + | + | / extern_class!( + | | struct BogusThreadKind; + | | + | | unsafe impl ClassType for BogusThreadKind { +... | + | | } + | | ); + | |_^ the trait `ValidThreadKind<(dyn ThreadKind + 'static)>` is not implemented for `BogusThreadKind` + | + = note: this error originates in the macro `$crate::__inner_extern_class` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0038]: the trait `ThreadKind` cannot be made into an object + --> ui/extern_class_thread_kind_invalid.rs + | + | / extern_class!( + | | struct BogusThreadKind; + | | + | | unsafe impl ClassType for BogusThreadKind { +... | + | | } + | | ); + | |_^ `ThreadKind` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit + --> $WORKSPACE/crates/objc2/src/top_level_traits.rs + | + | const __NOT_OBJECT_SAFE: (); + | ^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because it contains this associated `const` + = note: this error originates in the macro `$crate::__inner_extern_class` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/extern_class_thread_kind_main_send_sync.rs b/crates/test-ui/ui/extern_class_thread_kind_main_send_sync.rs new file mode 100644 index 000000000..cb2d4c40f --- /dev/null +++ b/crates/test-ui/ui/extern_class_thread_kind_main_send_sync.rs @@ -0,0 +1,26 @@ +use objc2::runtime::NSObject; +use objc2::{extern_class, ClassType, MainThreadOnly}; + +extern_class!( + struct SendAndOnlyMain; + + unsafe impl ClassType for SendAndOnlyMain { + type Super = NSObject; + type ThreadKind = dyn MainThreadOnly; + } +); + +unsafe impl Send for SendAndOnlyMain {} + +extern_class!( + struct SyncAndOnlyMain; + + unsafe impl ClassType for SyncAndOnlyMain { + type Super = NSObject; + type ThreadKind = dyn MainThreadOnly; + } +); + +unsafe impl Sync for SyncAndOnlyMain {} + +fn main() {} diff --git a/crates/test-ui/ui/extern_class_thread_kind_main_send_sync.stderr b/crates/test-ui/ui/extern_class_thread_kind_main_send_sync.stderr new file mode 100644 index 000000000..117aca46f --- /dev/null +++ b/crates/test-ui/ui/extern_class_thread_kind_main_send_sync.stderr @@ -0,0 +1,37 @@ +error[E0283]: type annotations needed + --> ui/extern_class_thread_kind_main_send_sync.rs + | + | / extern_class!( + | | struct SendAndOnlyMain; + | | + | | unsafe impl ClassType for SendAndOnlyMain { +... | + | | } + | | ); + | |_^ cannot infer type + | + = note: multiple `impl`s satisfying `SendAndOnlyMain: MainThreadOnlyDoesNotImplSendSync<_>` found in the `objc2` crate: + - impl MainThreadOnlyDoesNotImplSendSync<()> for Cls + where Cls: ?Sized; + - impl MainThreadOnlyDoesNotImplSendSync<__macro_helpers::class::ImplsSend> for Cls + where Cls: MainThreadOnly, Cls: Send, Cls: ?Sized; + = note: this error originates in the macro `$crate::__inner_extern_class` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0283]: type annotations needed + --> ui/extern_class_thread_kind_main_send_sync.rs + | + | / extern_class!( + | | struct SyncAndOnlyMain; + | | + | | unsafe impl ClassType for SyncAndOnlyMain { +... | + | | } + | | ); + | |_^ cannot infer type + | + = note: multiple `impl`s satisfying `SyncAndOnlyMain: MainThreadOnlyDoesNotImplSendSync<_>` found in the `objc2` crate: + - impl MainThreadOnlyDoesNotImplSendSync<()> for Cls + where Cls: ?Sized; + - impl MainThreadOnlyDoesNotImplSendSync<__macro_helpers::class::ImplsSync> for Cls + where Cls: MainThreadOnly, Cls: Sync, Cls: ?Sized; + = note: this error originates in the macro `$crate::__inner_extern_class` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/extern_class_thread_kind_main_to_any.rs b/crates/test-ui/ui/extern_class_thread_kind_main_to_any.rs new file mode 100644 index 000000000..c8d5a6d0a --- /dev/null +++ b/crates/test-ui/ui/extern_class_thread_kind_main_to_any.rs @@ -0,0 +1,22 @@ +use objc2::runtime::NSObject; +use objc2::{extern_class, AllocAnyThread, ClassType, MainThreadOnly}; + +extern_class!( + struct OnlyMain; + + unsafe impl ClassType for OnlyMain { + type Super = NSObject; + type ThreadKind = dyn MainThreadOnly; + } +); + +extern_class!( + struct AnyThreadButSubclassesOnlyMain; + + unsafe impl ClassType for AnyThreadButSubclassesOnlyMain { + type Super = OnlyMain; + type ThreadKind = dyn AllocAnyThread; + } +); + +fn main() {} diff --git a/crates/test-ui/ui/extern_class_thread_kind_main_to_any.stderr b/crates/test-ui/ui/extern_class_thread_kind_main_to_any.stderr new file mode 100644 index 000000000..c33a35f60 --- /dev/null +++ b/crates/test-ui/ui/extern_class_thread_kind_main_to_any.stderr @@ -0,0 +1,17 @@ +error[E0271]: type mismatch resolving `::ThreadKind == dyn AllocAnyThread` + --> ui/extern_class_thread_kind_main_to_any.rs + | + | / extern_class!( + | | struct AnyThreadButSubclassesOnlyMain; + | | + | | unsafe impl ClassType for AnyThreadButSubclassesOnlyMain { +... | + | | } + | | ); + | |_^ expected trait `AllocAnyThread`, found trait `MainThreadOnly` + | + = note: expected trait object `dyn AllocAnyThread` + found trait object `(dyn MainThreadOnly + 'static)` + = help: `(dyn MainThreadOnly + 'static)` implements `AllocAnyThread` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + = note: required for `AnyThreadButSubclassesOnlyMain` to implement `ValidThreadKind<(dyn AllocAnyThread + 'static)>` + = note: this error originates in the macro `$crate::__inner_extern_class` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/extern_class_wrong_mutability.rs b/crates/test-ui/ui/extern_class_wrong_mutability.rs deleted file mode 100644 index 4fa6f2171..000000000 --- a/crates/test-ui/ui/extern_class_wrong_mutability.rs +++ /dev/null @@ -1,22 +0,0 @@ -use objc2::runtime::NSObject; -use objc2::{extern_class, mutability, ClassType}; - -extern_class!( - pub struct MyMainThreadClass; - - unsafe impl ClassType for MyMainThreadClass { - type Super = NSObject; - type Mutability = mutability::MainThreadOnly; - } -); - -extern_class!( - pub struct MyAnyThreadClass; - - unsafe impl ClassType for MyAnyThreadClass { - type Super = MyMainThreadClass; - type Mutability = mutability::InteriorMutable; - } -); - -fn main() {} diff --git a/crates/test-ui/ui/extern_class_wrong_mutability.stderr b/crates/test-ui/ui/extern_class_wrong_mutability.stderr deleted file mode 100644 index 4b2ba6314..000000000 --- a/crates/test-ui/ui/extern_class_wrong_mutability.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0277]: the trait bound `MainThreadOnly: ValidSubclassMutability` is not satisfied - --> ui/extern_class_wrong_mutability.rs - | - | / extern_class!( - | | pub struct MyAnyThreadClass; - | | - | | unsafe impl ClassType for MyAnyThreadClass { -... | - | | } - | | ); - | |_^ the trait `ValidSubclassMutability` is not implemented for `MainThreadOnly` - | - = help: the trait `ValidSubclassMutability` is implemented for `MainThreadOnly` - = help: for that trait implementation, expected `MainThreadOnly`, found `InteriorMutable` -note: required by a bound in `assert_mutability_matches_superclass_mutability` - --> $WORKSPACE/crates/objc2/src/__macro_helpers/declare_class.rs - | - | pub fn assert_mutability_matches_superclass_mutability() - | ----------------------------------------------- required by a bound in this function -... - | ::Mutability: ValidSubclassMutability, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_mutability_matches_superclass_mutability` - = note: this error originates in the macro `$crate::__inner_extern_class` which comes from the expansion of the macro `extern_class` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/crates/test-ui/ui/extern_methods_bad_selector.rs b/crates/test-ui/ui/extern_methods_bad_selector.rs index 8b68edd09..6b8a060a1 100644 --- a/crates/test-ui/ui/extern_methods_bad_selector.rs +++ b/crates/test-ui/ui/extern_methods_bad_selector.rs @@ -1,12 +1,11 @@ use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( pub struct MyObject; unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_feature_flag.rs b/crates/test-ui/ui/extern_methods_feature_flag.rs index 1c042c944..37f7c8295 100644 --- a/crates/test-ui/ui/extern_methods_feature_flag.rs +++ b/crates/test-ui/ui/extern_methods_feature_flag.rs @@ -1,12 +1,11 @@ use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( pub struct MyTest; unsafe impl ClassType for MyTest { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_feature_flag.stderr b/crates/test-ui/ui/extern_methods_feature_flag.stderr index 03bf2edf7..c8d88cf0d 100644 --- a/crates/test-ui/ui/extern_methods_feature_flag.stderr +++ b/crates/test-ui/ui/extern_methods_feature_flag.stderr @@ -5,7 +5,7 @@ error[E0599]: no function or associated item named `disabled` found for struct ` | | pub struct MyTest; | | | | unsafe impl ClassType for MyTest { -... | + | | type Super = NSObject; | | } | | ); | |_- function or associated item `disabled` not found for this struct @@ -20,7 +20,7 @@ error[E0599]: no function or associated item named `disabled_inner1` found for s | | pub struct MyTest; | | | | unsafe impl ClassType for MyTest { -... | + | | type Super = NSObject; | | } | | ); | |_- function or associated item `disabled_inner1` not found for this struct @@ -30,7 +30,7 @@ error[E0599]: no function or associated item named `disabled_inner1` found for s | help: there is an associated function `enabled_inner1` with a similar name | -51 | MyTest::enabled_inner1(); +50 | MyTest::enabled_inner1(); | ~~~~~~~~~~~~~~ error[E0599]: no function or associated item named `disabled_inner2` found for struct `MyTest` in the current scope @@ -40,7 +40,7 @@ error[E0599]: no function or associated item named `disabled_inner2` found for s | | pub struct MyTest; | | | | unsafe impl ClassType for MyTest { -... | + | | type Super = NSObject; | | } | | ); | |_- function or associated item `disabled_inner2` not found for this struct @@ -50,5 +50,5 @@ error[E0599]: no function or associated item named `disabled_inner2` found for s | help: there is an associated function `enabled_inner2` with a similar name | -52 | MyTest::enabled_inner2(); +51 | MyTest::enabled_inner2(); | ~~~~~~~~~~~~~~ diff --git a/crates/test-ui/ui/extern_methods_invalid_receiver.rs b/crates/test-ui/ui/extern_methods_invalid_receiver.rs index c652b31b6..566273c5d 100644 --- a/crates/test-ui/ui/extern_methods_invalid_receiver.rs +++ b/crates/test-ui/ui/extern_methods_invalid_receiver.rs @@ -1,13 +1,12 @@ use objc2::rc::{Allocated, Retained}; use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( pub struct MyObject; unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_invalid_type.rs b/crates/test-ui/ui/extern_methods_invalid_type.rs index 66abe0520..55792f124 100644 --- a/crates/test-ui/ui/extern_methods_invalid_type.rs +++ b/crates/test-ui/ui/extern_methods_invalid_type.rs @@ -1,6 +1,6 @@ use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; use objc2_foundation::MainThreadMarker; extern_class!( @@ -8,7 +8,6 @@ extern_class!( unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_missing_method.rs b/crates/test-ui/ui/extern_methods_missing_method.rs index 608fac0da..977e0350a 100644 --- a/crates/test-ui/ui/extern_methods_missing_method.rs +++ b/crates/test-ui/ui/extern_methods_missing_method.rs @@ -1,12 +1,11 @@ use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( pub struct MyObject; unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_not_allowed_mutable.rs b/crates/test-ui/ui/extern_methods_not_allowed_mutable.rs index 3c6a23920..3aaa4d0d2 100644 --- a/crates/test-ui/ui/extern_methods_not_allowed_mutable.rs +++ b/crates/test-ui/ui/extern_methods_not_allowed_mutable.rs @@ -1,14 +1,13 @@ //! Test extern_methods! with mutable receivers that are not IsAllowedMutable. use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( pub struct MyObject; unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_selector_twice.rs b/crates/test-ui/ui/extern_methods_selector_twice.rs index 86cefef05..ae2cbd7c1 100644 --- a/crates/test-ui/ui/extern_methods_selector_twice.rs +++ b/crates/test-ui/ui/extern_methods_selector_twice.rs @@ -1,12 +1,11 @@ use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( pub struct MyObject; unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_variadic.rs b/crates/test-ui/ui/extern_methods_variadic.rs index 7e4cd4a1b..33c9a62a3 100644 --- a/crates/test-ui/ui/extern_methods_variadic.rs +++ b/crates/test-ui/ui/extern_methods_variadic.rs @@ -1,13 +1,12 @@ use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( pub struct MyObject; unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_wrong_arguments.rs b/crates/test-ui/ui/extern_methods_wrong_arguments.rs index 5e8eafd3b..a218c0bc3 100644 --- a/crates/test-ui/ui/extern_methods_wrong_arguments.rs +++ b/crates/test-ui/ui/extern_methods_wrong_arguments.rs @@ -1,12 +1,11 @@ use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; extern_class!( pub struct MyObject; unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/extern_methods_wrong_arguments_error.rs b/crates/test-ui/ui/extern_methods_wrong_arguments_error.rs index 19072c82a..0de208c4a 100644 --- a/crates/test-ui/ui/extern_methods_wrong_arguments_error.rs +++ b/crates/test-ui/ui/extern_methods_wrong_arguments_error.rs @@ -1,6 +1,6 @@ use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType}; +use objc2::{extern_class, extern_methods, ClassType}; use objc2_foundation::MainThreadMarker; extern_class!( @@ -8,7 +8,6 @@ extern_class!( unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/implement_protocol_missing_super.rs b/crates/test-ui/ui/implement_protocol_missing_super.rs index 1047dbd1c..372a73d55 100644 --- a/crates/test-ui/ui/implement_protocol_missing_super.rs +++ b/crates/test-ui/ui/implement_protocol_missing_super.rs @@ -1,6 +1,6 @@ //! Test that implementing certain traits like `NSURLSessionDelegate` requires //! super protocols like `NSObjectProtocol` to also be implemented. -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, ClassType, DeclaredClass, MainThreadOnly}; use objc2_foundation::{NSObject, NSURLSessionDelegate}; declare_class!( @@ -8,7 +8,7 @@ declare_class!( unsafe impl ClassType for CustomObject { type Super = NSObject; - type Mutability = mutability::MainThreadOnly; + type ThreadKind = dyn MainThreadOnly; const NAME: &'static str = "CustomObject"; } diff --git a/crates/test-ui/ui/main_thread_only_not_allocable.rs b/crates/test-ui/ui/main_thread_only_not_allocable.rs index b5b2a6f58..d695670a7 100644 --- a/crates/test-ui/ui/main_thread_only_not_allocable.rs +++ b/crates/test-ui/ui/main_thread_only_not_allocable.rs @@ -1,12 +1,14 @@ use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +#[expect(unused_imports)] +use objc2::AllocAnyThread; +use objc2::{declare_class, ClassType, DeclaredClass, MainThreadOnly}; declare_class!( struct MyMainThreadOnlyClass; unsafe impl ClassType for MyMainThreadOnlyClass { type Super = NSObject; - type Mutability = mutability::MainThreadOnly; + type ThreadKind = dyn MainThreadOnly; const NAME: &'static str = "MyMainThreadOnlyClass"; } diff --git a/crates/test-ui/ui/main_thread_only_not_allocable.stderr b/crates/test-ui/ui/main_thread_only_not_allocable.stderr index eb43ef923..1a177e9e0 100644 --- a/crates/test-ui/ui/main_thread_only_not_allocable.stderr +++ b/crates/test-ui/ui/main_thread_only_not_allocable.stderr @@ -1,18 +1,15 @@ -error[E0277]: the trait bound `MainThreadOnly: mutability::MutabilityIsAllocableAnyThread` is not satisfied - --> ui/main_thread_only_not_allocable.rs - | - | let _ = MyMainThreadOnlyClass::alloc(); - | ^^^^^^^^^^^^^^^^^^^^^ the trait `mutability::MutabilityIsAllocableAnyThread` is not implemented for `MainThreadOnly`, which is required by `MyMainThreadOnlyClass: IsAllocableAnyThread` - | - = help: the following other types implement trait `mutability::MutabilityIsAllocableAnyThread`: - InteriorMutable - Root - = note: required for `MyMainThreadOnlyClass` to implement `IsAllocableAnyThread` -note: required by a bound in `objc2::ClassType::alloc` - --> $WORKSPACE/crates/objc2/src/top_level_traits.rs - | - | fn alloc() -> Allocated - | ----- required by a bound in this associated function - | where - | Self: IsAllocableAnyThread + Sized, - | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `ClassType::alloc` +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> ui/main_thread_only_not_allocable.rs + | + | let _ = MyMainThreadOnlyClass::alloc(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^-- argument #1 of type `MainThreadMarker` is missing + | +note: associated function defined here + --> $WORKSPACE/crates/objc2/src/top_level_traits.rs + | + | fn alloc(mtm: MainThreadMarker) -> Allocated + | ^^^^^ +help: provide the argument + | +19 | let _ = MyMainThreadOnlyClass::alloc(/* MainThreadMarker */); + | ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/crates/test-ui/ui/mainthreadmarker_from_nsobject.stderr b/crates/test-ui/ui/mainthreadmarker_from_nsobject.stderr index 664c35c79..692afb97d 100644 --- a/crates/test-ui/ui/mainthreadmarker_from_nsobject.stderr +++ b/crates/test-ui/ui/mainthreadmarker_from_nsobject.stderr @@ -1,9 +1,11 @@ -error[E0277]: the trait bound `objc2::mutability::Root: objc2::mutability::MutabilityIsMainThreadOnly` is not satisfied +error[E0271]: type mismatch resolving `::ThreadKind == dyn MainThreadOnly` --> ui/mainthreadmarker_from_nsobject.rs | | let mtm = MainThreadMarker::from(&*obj); - | ^^^^^^^^^^^^^^^^ the trait `objc2::mutability::MutabilityIsMainThreadOnly` is not implemented for `objc2::mutability::Root`, which is required by `MainThreadMarker: From<&NSObject>` + | ^^^^^^^^^^^^^^^^ expected trait `MainThreadOnly`, found trait `AllocAnyThread` | - = help: the trait `objc2::mutability::MutabilityIsMainThreadOnly` is implemented for `objc2::mutability::MainThreadOnly` - = note: required for `NSObject` to implement `objc2::mutability::IsMainThreadOnly` + = note: expected trait object `dyn objc2::top_level_traits::MainThreadOnly` + found trait object `(dyn objc2::top_level_traits::AllocAnyThread + 'static)` + = help: `(dyn objc2::top_level_traits::AllocAnyThread + 'static)` implements `MainThreadOnly` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + = note: required for `NSObject` to implement `objc2::top_level_traits::MainThreadOnly` = note: required for `MainThreadMarker` to implement `From<&NSObject>` diff --git a/crates/test-ui/ui/msg_send_id_invalid_error.stderr b/crates/test-ui/ui/msg_send_id_invalid_error.stderr index 0ebc18d2b..7ad4711a9 100644 --- a/crates/test-ui/ui/msg_send_id_invalid_error.stderr +++ b/crates/test-ui/ui/msg_send_id_invalid_error.stderr @@ -8,15 +8,17 @@ error[E0308]: mismatched types found enum `Result, Retained<_>>` = note: this error originates in the macro `$crate::__msg_send_id_helper` which comes from the expansion of the macro `msg_send_id` (in Nightly builds, run with -Z macro-backtrace for more info) -error[E0308]: mismatched types +error[E0599]: no function or associated item named `alloc` found for struct `NSObject` in the current scope --> ui/msg_send_id_invalid_error.rs | | unsafe { msg_send_id![NSObject::alloc(), initWithError: _] }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Result, ...>`, found `Result, ...>` + | ^^^^^ function or associated item not found in `NSObject` | - = note: expected enum `Result, Retained>` - found enum `Result, Retained<_>>` - = note: this error originates in the macro `$crate::__msg_send_id_helper` which comes from the expansion of the macro `msg_send_id` (in Nightly builds, run with -Z macro-backtrace for more info) + = help: items from traits can only be used if the trait is in scope +help: trait `AllocAnyThread` which provides `alloc` is implemented but not in scope; perhaps you want to import it + | +2 + use objc2::AllocAnyThread; + | error[E0271]: type mismatch resolving `> as MaybeUnwrap>::Input == Allocated<_>` --> ui/msg_send_id_invalid_error.rs diff --git a/crates/test-ui/ui/mutability_traits_unimplementable.rs b/crates/test-ui/ui/mutability_traits_unimplementable.rs deleted file mode 100644 index 4327d84b4..000000000 --- a/crates/test-ui/ui/mutability_traits_unimplementable.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! Check that `mutability` traits are not implementable manually. -use objc2::runtime::NSObject; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; - -declare_class!( - struct CustomObject; - - unsafe impl ClassType for CustomObject { - type Super = NSObject; - type Mutability = mutability::MainThreadOnly; - const NAME: &'static str = "CustomObject"; - } - - impl DeclaredClass for CustomObject {} -); - -unsafe impl mutability::IsAllocableAnyThread for CustomObject {} - -fn main() {} diff --git a/crates/test-ui/ui/mutability_traits_unimplementable.stderr b/crates/test-ui/ui/mutability_traits_unimplementable.stderr deleted file mode 100644 index 0212148d5..000000000 --- a/crates/test-ui/ui/mutability_traits_unimplementable.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0119]: conflicting implementations of trait `IsAllocableAnyThread` for type `CustomObject` - --> ui/mutability_traits_unimplementable.rs - | - | unsafe impl mutability::IsAllocableAnyThread for CustomObject {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `objc2`: - - impl IsAllocableAnyThread for T - where T: ClassType, ::Mutability: mutability::MutabilityIsAllocableAnyThread, T: ?Sized; diff --git a/crates/test-ui/ui/mutability_traits_unimplementable2.rs b/crates/test-ui/ui/mutability_traits_unimplementable2.rs deleted file mode 100644 index 40451764c..000000000 --- a/crates/test-ui/ui/mutability_traits_unimplementable2.rs +++ /dev/null @@ -1,8 +0,0 @@ -//! Check that `mutability` traits are not implementable manually. -use objc2::mutability; - -struct CustomStruct; - -unsafe impl mutability::IsAllocableAnyThread for CustomStruct {} - -fn main() {} diff --git a/crates/test-ui/ui/mutability_traits_unimplementable2.stderr b/crates/test-ui/ui/mutability_traits_unimplementable2.stderr deleted file mode 100644 index 3fb0a358d..000000000 --- a/crates/test-ui/ui/mutability_traits_unimplementable2.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0277]: the trait bound `CustomStruct: mutability::private_traits::Sealed` is not satisfied - --> ui/mutability_traits_unimplementable2.rs - | - | unsafe impl mutability::IsAllocableAnyThread for CustomStruct {} - | ^^^^^^^^^^^^ the trait `ClassType` is not implemented for `CustomStruct`, which is required by `CustomStruct: mutability::private_traits::Sealed` - | - = help: the following other types implement trait `ClassType`: - NSObject - __NSProxy - = note: required for `CustomStruct` to implement `mutability::private_traits::Sealed` -note: required by a bound in `IsAllocableAnyThread` - --> $WORKSPACE/crates/objc2/src/mutability.rs - | - | pub unsafe trait IsAllocableAnyThread: private_traits::Sealed {} - | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `IsAllocableAnyThread` - = note: `IsAllocableAnyThread` is a "sealed trait", because to implement it you also need to implement `objc2::mutability::private_traits::Sealed`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it - = help: the following types implement the trait: - objc2::runtime::ProtocolObject

- objc2::runtime::AnyObject - T diff --git a/crates/test-ui/ui/ns_copying_without_copy_helper.rs b/crates/test-ui/ui/ns_copying_without_copy_helper.rs index cb43692a1..787dcad6d 100644 --- a/crates/test-ui/ui/ns_copying_without_copy_helper.rs +++ b/crates/test-ui/ui/ns_copying_without_copy_helper.rs @@ -1,4 +1,4 @@ -use objc2::{extern_class, mutability, ClassType}; +use objc2::{extern_class, ClassType}; use objc2_foundation::{NSCopying, NSMutableCopying, NSObject}; extern_class!( @@ -6,7 +6,6 @@ extern_class!( unsafe impl ClassType for MyObj { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/crates/test-ui/ui/thread_kind_traits_unimplementable.rs b/crates/test-ui/ui/thread_kind_traits_unimplementable.rs new file mode 100644 index 000000000..ea2de6246 --- /dev/null +++ b/crates/test-ui/ui/thread_kind_traits_unimplementable.rs @@ -0,0 +1,33 @@ +//! Check that `MainThreadOnly`/`AllocAnyThread` traits are not implementable manually. +use objc2::runtime::NSObject; +use objc2::{declare_class, AllocAnyThread, ClassType, DeclaredClass, MainThreadOnly}; + +declare_class!( + struct Normal; + + unsafe impl ClassType for Normal { + type Super = NSObject; + type ThreadKind = dyn AllocAnyThread; + const NAME: &'static str = "Normal"; + } + + impl DeclaredClass for Normal {} +); + +unsafe impl MainThreadOnly for Normal {} + +declare_class!( + struct OnlyMain; + + unsafe impl ClassType for OnlyMain { + type Super = NSObject; + type ThreadKind = dyn MainThreadOnly; + const NAME: &'static str = "OnlyMain"; + } + + impl DeclaredClass for OnlyMain {} +); + +unsafe impl AllocAnyThread for OnlyMain {} + +fn main() {} diff --git a/crates/test-ui/ui/thread_kind_traits_unimplementable.stderr b/crates/test-ui/ui/thread_kind_traits_unimplementable.stderr new file mode 100644 index 000000000..7f80056f7 --- /dev/null +++ b/crates/test-ui/ui/thread_kind_traits_unimplementable.stderr @@ -0,0 +1,39 @@ +error[E0271]: type mismatch resolving `::ThreadKind == dyn MainThreadOnly` + --> ui/thread_kind_traits_unimplementable.rs + | + | unsafe impl MainThreadOnly for Normal {} + | ^^^^^^ expected trait `MainThreadOnly`, found trait `AllocAnyThread` + | + = note: expected trait object `dyn MainThreadOnly` + found trait object `(dyn AllocAnyThread + 'static)` + = help: `(dyn AllocAnyThread + 'static)` implements `MainThreadOnly` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + = note: required for `Normal` to implement `objc2::top_level_traits::private::SealedMainThreadOnly` +note: required by a bound in `MainThreadOnly` + --> $WORKSPACE/crates/objc2/src/top_level_traits.rs + | + | pub unsafe trait MainThreadOnly: private::SealedMainThreadOnly { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MainThreadOnly` + = note: `MainThreadOnly` is a "sealed trait", because to implement it you also need to implement `objc2::top_level_traits::private::SealedMainThreadOnly`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it + = help: the following types implement the trait: + objc2::runtime::ProtocolObject

+ T + +error[E0271]: type mismatch resolving `::ThreadKind == dyn AllocAnyThread` + --> ui/thread_kind_traits_unimplementable.rs + | + | unsafe impl AllocAnyThread for OnlyMain {} + | ^^^^^^^^ expected trait `AllocAnyThread`, found trait `MainThreadOnly` + | + = note: expected trait object `dyn AllocAnyThread` + found trait object `(dyn MainThreadOnly + 'static)` + = help: `(dyn MainThreadOnly + 'static)` implements `AllocAnyThread` so you could box the found value and coerce it to the trait object `Box`, you will have to change the expected type as well + = note: required for `OnlyMain` to implement `objc2::top_level_traits::private::SealedAllocAnyThread` +note: required by a bound in `AllocAnyThread` + --> $WORKSPACE/crates/objc2/src/top_level_traits.rs + | + | pub unsafe trait AllocAnyThread: private::SealedAllocAnyThread { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AllocAnyThread` + = note: `AllocAnyThread` is a "sealed trait", because to implement it you also need to implement `objc2::top_level_traits::private::SealedAllocAnyThread`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it + = help: the following types implement the trait: + objc2::runtime::ProtocolObject

+ T diff --git a/crates/test-ui/ui/thread_kind_traits_unimplementable2.rs b/crates/test-ui/ui/thread_kind_traits_unimplementable2.rs new file mode 100644 index 000000000..552a88a1b --- /dev/null +++ b/crates/test-ui/ui/thread_kind_traits_unimplementable2.rs @@ -0,0 +1,10 @@ +//! Check that `AllocAnyThread`/`MainThreadOnly` traits are not implementable manually. +use objc2::{AllocAnyThread, MainThreadOnly}; + +struct CustomStruct; + +unsafe impl AllocAnyThread for CustomStruct {} + +unsafe impl MainThreadOnly for CustomStruct {} + +fn main() {} diff --git a/crates/test-ui/ui/thread_kind_traits_unimplementable2.stderr b/crates/test-ui/ui/thread_kind_traits_unimplementable2.stderr new file mode 100644 index 000000000..4ccc9b792 --- /dev/null +++ b/crates/test-ui/ui/thread_kind_traits_unimplementable2.stderr @@ -0,0 +1,39 @@ +error[E0277]: the trait bound `CustomStruct: objc2::top_level_traits::private::SealedAllocAnyThread` is not satisfied + --> ui/thread_kind_traits_unimplementable2.rs + | + | unsafe impl AllocAnyThread for CustomStruct {} + | ^^^^^^^^^^^^ the trait `ClassType` is not implemented for `CustomStruct`, which is required by `CustomStruct: objc2::top_level_traits::private::SealedAllocAnyThread` + | + = help: the following other types implement trait `ClassType`: + NSObject + __NSProxy + = note: required for `CustomStruct` to implement `objc2::top_level_traits::private::SealedAllocAnyThread` +note: required by a bound in `AllocAnyThread` + --> $WORKSPACE/crates/objc2/src/top_level_traits.rs + | + | pub unsafe trait AllocAnyThread: private::SealedAllocAnyThread { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `AllocAnyThread` + = note: `AllocAnyThread` is a "sealed trait", because to implement it you also need to implement `objc2::top_level_traits::private::SealedAllocAnyThread`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it + = help: the following types implement the trait: + objc2::runtime::ProtocolObject

+ T + +error[E0277]: the trait bound `CustomStruct: objc2::top_level_traits::private::SealedMainThreadOnly` is not satisfied + --> ui/thread_kind_traits_unimplementable2.rs + | + | unsafe impl MainThreadOnly for CustomStruct {} + | ^^^^^^^^^^^^ the trait `ClassType` is not implemented for `CustomStruct`, which is required by `CustomStruct: objc2::top_level_traits::private::SealedMainThreadOnly` + | + = help: the following other types implement trait `ClassType`: + NSObject + __NSProxy + = note: required for `CustomStruct` to implement `objc2::top_level_traits::private::SealedMainThreadOnly` +note: required by a bound in `MainThreadOnly` + --> $WORKSPACE/crates/objc2/src/top_level_traits.rs + | + | pub unsafe trait MainThreadOnly: private::SealedMainThreadOnly { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MainThreadOnly` + = note: `MainThreadOnly` is a "sealed trait", because to implement it you also need to implement `objc2::top_level_traits::private::SealedMainThreadOnly`, which is not accessible; this is usually done to force you to use one of the provided types that already implement it + = help: the following types implement the trait: + objc2::runtime::ProtocolObject

+ T diff --git a/crates/test-ui/ui/wrong_optional.rs b/crates/test-ui/ui/wrong_optional.rs index 672dfaec5..6cc899903 100644 --- a/crates/test-ui/ui/wrong_optional.rs +++ b/crates/test-ui/ui/wrong_optional.rs @@ -1,13 +1,12 @@ use objc2::rc::Retained; use objc2::runtime::NSObject; -use objc2::{declare_class, extern_class, extern_methods, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, extern_class, extern_methods, ClassType, DeclaredClass}; extern_class!( pub struct MyObject; unsafe impl ClassType for MyObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); @@ -34,7 +33,6 @@ declare_class!( unsafe impl ClassType for CustomObject1 { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject1"; } @@ -53,7 +51,6 @@ declare_class!( unsafe impl ClassType for CustomObject2 { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "CustomObject2"; } diff --git a/crates/tests/src/test_declare_class_protocol.rs b/crates/tests/src/test_declare_class_protocol.rs index e531f433e..96af1b515 100644 --- a/crates/tests/src/test_declare_class_protocol.rs +++ b/crates/tests/src/test_declare_class_protocol.rs @@ -1,5 +1,4 @@ #![cfg(feature = "all")] -use objc2::mutability::InteriorMutable; use objc2::rc::Retained; use objc2::runtime::{NSObject, NSZone}; use objc2::{declare_class, ClassType, DeclaredClass, ProtocolType}; @@ -13,7 +12,6 @@ fn test_declare_class_duplicate() { unsafe impl ClassType for Custom1 { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestDeclareClassDuplicate"; } @@ -25,7 +23,6 @@ fn test_declare_class_duplicate() { unsafe impl ClassType for Custom2 { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestDeclareClassDuplicate"; } @@ -44,7 +41,6 @@ fn test_declare_class_protocol() { unsafe impl ClassType for Custom { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestDeclareClassProtocolNotFound"; } @@ -73,7 +69,6 @@ fn test_declare_class_invalid_method() { unsafe impl ClassType for Custom { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestDeclareClassInvalidMethod"; } @@ -100,7 +95,6 @@ fn test_declare_class_missing_protocol_method() { unsafe impl ClassType for Custom { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestDeclareClassMissingProtocolMethod"; } @@ -122,7 +116,6 @@ fn test_declare_class_invalid_protocol_method() { unsafe impl ClassType for Custom { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestDeclareClassInvalidProtocolMethod"; } @@ -151,7 +144,6 @@ fn test_declare_class_extra_protocol_method() { unsafe impl ClassType for Custom { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "TestDeclareClassExtraProtocolMethod"; } diff --git a/crates/tests/src/test_foundation_retain_semantics.rs b/crates/tests/src/test_foundation_retain_semantics.rs index 4b8bd7a80..78b5346f8 100644 --- a/crates/tests/src/test_foundation_retain_semantics.rs +++ b/crates/tests/src/test_foundation_retain_semantics.rs @@ -1,7 +1,6 @@ #![cfg(feature = "all")] use std::ptr; -use objc2::mutability::InteriorMutable; use objc2::rc::Retained; use objc2::{declare_class, extern_methods, ClassType, DeclaredClass}; use objc2_foundation::{ @@ -358,7 +357,6 @@ declare_class!( unsafe impl ClassType for NSCopyingRcTestObject { type Super = RcTestObject; - type Mutability = InteriorMutable; const NAME: &'static str = "NSCopyingRcTestObject"; } diff --git a/crates/tests/src/test_object.rs b/crates/tests/src/test_object.rs index 851a04d1b..ee5b7b6fd 100644 --- a/crates/tests/src/test_object.rs +++ b/crates/tests/src/test_object.rs @@ -8,9 +8,7 @@ use objc2::runtime::{ AnyClass, AnyObject, AnyProtocol, Bool, NSObject, NSObjectProtocol, ProtocolObject, }; use objc2::sel; -use objc2::{ - class, extern_protocol, msg_send, msg_send_id, mutability, ClassType, Message, ProtocolType, -}; +use objc2::{class, extern_protocol, msg_send, msg_send_id, ClassType, Message, ProtocolType}; #[cfg(feature = "all")] use objc2_foundation::NSNumber; @@ -90,7 +88,7 @@ unsafe impl Message for MyTestObject {} unsafe impl ClassType for MyTestObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; + type ThreadKind = ::ThreadKind; const NAME: &'static str = "MyTestObject"; #[cfg(all(target_vendor = "apple", target_arch = "aarch64"))] diff --git a/crates/tests/src/test_simd_return.rs b/crates/tests/src/test_simd_return.rs index 07765d27a..032fbb72a 100644 --- a/crates/tests/src/test_simd_return.rs +++ b/crates/tests/src/test_simd_return.rs @@ -1,14 +1,13 @@ use core::ffi::{c_char, c_float}; use objc2::runtime::NSObject; -use objc2::{extern_class, extern_methods, mutability, ClassType, Encode, Encoding}; +use objc2::{extern_class, extern_methods, ClassType, Encode, Encoding}; extern_class!( struct TestSimdReturn; unsafe impl ClassType for TestSimdReturn { type Super = NSObject; - type Mutability = mutability::InteriorMutable; } ); diff --git a/framework-crates/objc2-app-kit/examples/delegate.rs b/framework-crates/objc2-app-kit/examples/delegate.rs index ded06fa03..63b2ef1a6 100644 --- a/framework-crates/objc2-app-kit/examples/delegate.rs +++ b/framework-crates/objc2-app-kit/examples/delegate.rs @@ -1,7 +1,9 @@ #![deny(unsafe_op_in_unsafe_fn)] use objc2::rc::Retained; use objc2::runtime::ProtocolObject; -use objc2::{declare_class, msg_send_id, mutability, ClassType, DeclaredClass, MainThreadMarker}; +use objc2::{ + declare_class, msg_send_id, ClassType, DeclaredClass, MainThreadMarker, MainThreadOnly, +}; use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy, NSApplicationDelegate}; use objc2_foundation::{ ns_string, NSCopying, NSNotification, NSObject, NSObjectProtocol, NSString, @@ -23,11 +25,10 @@ declare_class!( // SAFETY: // - The superclass NSObject does not have any subclassing requirements. - // - Main thread only mutability is correct, since this is an application delegate. // - `AppDelegate` does not implement `Drop`. unsafe impl ClassType for AppDelegate { type Super = NSObject; - type Mutability = mutability::MainThreadOnly; + type ThreadKind = dyn MainThreadOnly; const NAME: &'static str = "MyAppDelegate"; } @@ -54,7 +55,7 @@ declare_class!( impl AppDelegate { fn new(ivar: u8, another_ivar: bool, mtm: MainThreadMarker) -> Retained { - let this = Self::alloc_main_thread(mtm); + let this = Self::alloc(mtm); let this = this.set_ivars(Ivars { ivar, another_ivar, diff --git a/framework-crates/objc2-authentication-services/src/lib.rs b/framework-crates/objc2-authentication-services/src/lib.rs index ddca37f64..cdd0399aa 100644 --- a/framework-crates/objc2-authentication-services/src/lib.rs +++ b/framework-crates/objc2-authentication-services/src/lib.rs @@ -22,7 +22,7 @@ mod generated; pub use self::generated::*; use objc2::runtime::NSObject; -use objc2::{extern_class, mutability, ClassType}; +use objc2::{extern_class, ClassType, MainThreadOnly}; // TODO: UIViewController on iOS, NSViewController on macOS pub type ASViewController = NSObject; @@ -43,7 +43,7 @@ extern_class!( #[cfg(feature = "ASCredentialProviderViewController")] unsafe impl ClassType for ASCredentialProviderViewController { type Super = ASViewController; - type Mutability = mutability::MainThreadOnly; + type ThreadKind = dyn MainThreadOnly; } ); @@ -55,7 +55,7 @@ extern_class!( #[cfg(feature = "ASAccountAuthenticationModificationViewController")] unsafe impl ClassType for ASAccountAuthenticationModificationViewController { type Super = ASViewController; - type Mutability = mutability::MainThreadOnly; + type ThreadKind = dyn MainThreadOnly; } ); @@ -67,6 +67,6 @@ extern_class!( #[cfg(feature = "ASAuthorizationAppleIDButton")] unsafe impl ClassType for ASAuthorizationAppleIDButton { type Super = ASControl; - type Mutability = mutability::MainThreadOnly; + type ThreadKind = dyn MainThreadOnly; } ); diff --git a/framework-crates/objc2-foundation/examples/speech_synthesis.rs b/framework-crates/objc2-foundation/examples/speech_synthesis.rs index 9ba5ca624..336fb5714 100644 --- a/framework-crates/objc2-foundation/examples/speech_synthesis.rs +++ b/framework-crates/objc2-foundation/examples/speech_synthesis.rs @@ -11,7 +11,6 @@ use std::thread; use std::time::Duration; -use objc2::mutability::InteriorMutable; use objc2::rc::Retained; use objc2::{extern_class, msg_send, msg_send_id, ClassType}; use objc2_foundation::{ns_string, NSObject, NSString}; @@ -32,7 +31,6 @@ mod implementation { unsafe impl ClassType for Synthesizer { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "NSSpeechSynthesizer"; } ); @@ -100,6 +98,7 @@ mod implementation { #[cfg(all(target_vendor = "apple", not(target_os = "macos")))] mod implementation { use super::*; + use objc2::AllocAnyThread; #[link(name = "AVFoundation", kind = "framework")] extern "C" {} @@ -111,7 +110,6 @@ mod implementation { unsafe impl ClassType for Synthesizer { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "AVSpeechSynthesizer"; } ); @@ -137,7 +135,6 @@ mod implementation { unsafe impl ClassType for Utterance { type Super = NSObject; - type Mutability = InteriorMutable; const NAME: &'static str = "AVSpeechUtterance"; } ); diff --git a/framework-crates/objc2-foundation/src/array.rs b/framework-crates/objc2-foundation/src/array.rs index cfd6b8714..2e43c92e8 100644 --- a/framework-crates/objc2-foundation/src/array.rs +++ b/framework-crates/objc2-foundation/src/array.rs @@ -6,7 +6,7 @@ use core::mem; use core::ptr::NonNull; use objc2::rc::{Retained, RetainedFromIterator}; -use objc2::{msg_send, ClassType, Message}; +use objc2::{msg_send, AllocAnyThread, Message}; #[cfg(feature = "NSEnumerator")] use crate::iter; diff --git a/framework-crates/objc2-foundation/src/attributed_string.rs b/framework-crates/objc2-foundation/src/attributed_string.rs index 2f0be1bde..658898c12 100644 --- a/framework-crates/objc2-foundation/src/attributed_string.rs +++ b/framework-crates/objc2-foundation/src/attributed_string.rs @@ -2,7 +2,7 @@ use core::fmt; use core::panic::{RefUnwindSafe, UnwindSafe}; use objc2::rc::Retained; -use objc2::ClassType; +use objc2::AllocAnyThread; use crate::Foundation::*; diff --git a/framework-crates/objc2-foundation/src/copying.rs b/framework-crates/objc2-foundation/src/copying.rs index 2a5c4e03d..9cf453452 100644 --- a/framework-crates/objc2-foundation/src/copying.rs +++ b/framework-crates/objc2-foundation/src/copying.rs @@ -96,7 +96,7 @@ extern_protocol!( /// Implement `NSCopying` for an externally defined class. /// /// ``` - /// use objc2::{ClassType, extern_class, mutability::InteriorMutable}; + /// use objc2::{ClassType, extern_class}; /// use objc2_foundation::{CopyingHelper, NSCopying, NSObject}; /// /// extern_class!( @@ -104,7 +104,6 @@ extern_protocol!( /// /// unsafe impl ClassType for ExampleClass { /// type Super = NSObject; - /// type Mutability = InteriorMutable; /// # const NAME: &'static str = "NSData"; /// } /// ); @@ -120,7 +119,7 @@ extern_protocol!( /// Implement `NSCopying` for a custom class. /// /// ``` - /// use objc2::{declare_class, msg_send_id, mutability::InteriorMutable, ClassType, DeclaredClass}; + /// use objc2::{declare_class, msg_send_id, AllocAnyThread, ClassType, DeclaredClass}; /// use objc2::rc::Retained; /// use objc2::runtime::NSZone; /// use objc2_foundation::{CopyingHelper, NSCopying, NSObject}; @@ -130,7 +129,6 @@ extern_protocol!( /// /// unsafe impl ClassType for CustomClass { /// type Super = NSObject; - /// type Mutability = InteriorMutable; /// const NAME: &'static str = "CustomClass"; /// } /// diff --git a/framework-crates/objc2-foundation/src/data.rs b/framework-crates/objc2-foundation/src/data.rs index 4e33d8855..b8129e6bd 100644 --- a/framework-crates/objc2-foundation/src/data.rs +++ b/framework-crates/objc2-foundation/src/data.rs @@ -11,7 +11,7 @@ use core::slice::{self}; use objc2::rc::Retained; #[cfg(feature = "block2")] use objc2::rc::RetainedFromIterator; -use objc2::{extern_methods, ClassType}; +use objc2::{extern_methods, AllocAnyThread}; use crate::Foundation::{NSData, NSMutableData}; diff --git a/framework-crates/objc2-foundation/src/dictionary.rs b/framework-crates/objc2-foundation/src/dictionary.rs index 60edd83bc..a887b6061 100644 --- a/framework-crates/objc2-foundation/src/dictionary.rs +++ b/framework-crates/objc2-foundation/src/dictionary.rs @@ -9,7 +9,7 @@ use objc2::rc::Retained; #[cfg(feature = "NSObject")] use objc2::runtime::ProtocolObject; #[cfg(feature = "NSObject")] -use objc2::ClassType; +use objc2::AllocAnyThread; use objc2::Message; #[cfg(feature = "NSEnumerator")] diff --git a/framework-crates/objc2-foundation/src/error.rs b/framework-crates/objc2-foundation/src/error.rs index 39c31a535..0093c602e 100644 --- a/framework-crates/objc2-foundation/src/error.rs +++ b/framework-crates/objc2-foundation/src/error.rs @@ -16,7 +16,7 @@ impl NSError { code: objc2::ffi::NSInteger, domain: &crate::NSErrorDomain, ) -> objc2::rc::Retained { - use objc2::ClassType; + use objc2::AllocAnyThread; // SAFETY: `domain` and `user_info` are copied to the error object, so // even if the `&NSString` came from a `&mut NSMutableString`, we're // still good! diff --git a/framework-crates/objc2-foundation/src/exception.rs b/framework-crates/objc2-foundation/src/exception.rs index 3bab074de..8451efd01 100644 --- a/framework-crates/objc2-foundation/src/exception.rs +++ b/framework-crates/objc2-foundation/src/exception.rs @@ -37,7 +37,7 @@ impl NSException { reason: Option<&crate::Foundation::NSString>, user_info: Option<&crate::Foundation::NSDictionary>, ) -> Option> { - use objc2::ClassType; + use objc2::AllocAnyThread; unsafe { objc2::msg_send_id![ diff --git a/framework-crates/objc2-foundation/src/set.rs b/framework-crates/objc2-foundation/src/set.rs index 4c0e6bf73..6815c5e39 100644 --- a/framework-crates/objc2-foundation/src/set.rs +++ b/framework-crates/objc2-foundation/src/set.rs @@ -4,7 +4,7 @@ use alloc::vec::Vec; use core::fmt; use objc2::rc::{Retained, RetainedFromIterator}; -use objc2::{msg_send, ClassType, Message}; +use objc2::{msg_send, AllocAnyThread, Message}; #[cfg(feature = "NSEnumerator")] use crate::iter; diff --git a/framework-crates/objc2-foundation/src/string.rs b/framework-crates/objc2-foundation/src/string.rs index fd24ffea1..6b77ae47d 100644 --- a/framework-crates/objc2-foundation/src/string.rs +++ b/framework-crates/objc2-foundation/src/string.rs @@ -12,7 +12,7 @@ use std::os::raw::c_void; use objc2::msg_send_id; use objc2::rc::{autoreleasepool_leaking, Allocated, AutoreleasePool, Retained}; use objc2::runtime::__nsstring::{nsstring_len, nsstring_to_str, UTF8_ENCODING}; -use objc2::{ClassType, Message}; +use objc2::{AllocAnyThread, Message}; use crate::{NSMutableString, NSString}; diff --git a/framework-crates/objc2-foundation/src/tests/auto_traits.rs b/framework-crates/objc2-foundation/src/tests/auto_traits.rs index aefc5f7ba..d32e0e97c 100644 --- a/framework-crates/objc2-foundation/src/tests/auto_traits.rs +++ b/framework-crates/objc2-foundation/src/tests/auto_traits.rs @@ -6,7 +6,7 @@ use static_assertions::assert_not_impl_any; use crate::*; use objc2::rc::Retained; use objc2::runtime::AnyObject; -use objc2::{declare_class, mutability, ClassType, DeclaredClass}; +use objc2::{declare_class, ClassType, DeclaredClass}; // We expect most Foundation types to be UnwindSafe and RefUnwindSafe, // since they follow Rust's usual mutability rules (&T = immutable). @@ -34,7 +34,6 @@ declare_class!( unsafe impl ClassType for SendSyncObject { type Super = NSObject; - type Mutability = mutability::InteriorMutable; const NAME: &'static str = "SendSyncObject"; } diff --git a/framework-crates/objc2-foundation/src/tests/mutable_array.rs b/framework-crates/objc2-foundation/src/tests/mutable_array.rs index 09f9e763a..0cdd41b7e 100644 --- a/framework-crates/objc2-foundation/src/tests/mutable_array.rs +++ b/framework-crates/objc2-foundation/src/tests/mutable_array.rs @@ -1,7 +1,7 @@ #![cfg(feature = "NSArray")] use objc2::rc::Allocated; use objc2::runtime::AnyObject; -use objc2::ClassType; +use objc2::AllocAnyThread; use crate::{NSMutableArray, NSObject}; diff --git a/framework-crates/objc2-foundation/src/uuid.rs b/framework-crates/objc2-foundation/src/uuid.rs index 1a97b9ced..0a380861d 100644 --- a/framework-crates/objc2-foundation/src/uuid.rs +++ b/framework-crates/objc2-foundation/src/uuid.rs @@ -4,7 +4,7 @@ use core::panic::{RefUnwindSafe, UnwindSafe}; use objc2::encode::{Encode, Encoding, RefEncode}; use objc2::rc::{Allocated, Retained}; -use objc2::{extern_methods, ClassType}; +use objc2::{extern_methods, AllocAnyThread}; use crate::Foundation::NSUUID; diff --git a/framework-crates/objc2-foundation/src/value.rs b/framework-crates/objc2-foundation/src/value.rs index 168f36561..b4608aebe 100644 --- a/framework-crates/objc2-foundation/src/value.rs +++ b/framework-crates/objc2-foundation/src/value.rs @@ -8,7 +8,7 @@ use std::ffi::{CStr, CString}; use objc2::encode::Encode; use objc2::rc::Retained; -use objc2::ClassType; +use objc2::AllocAnyThread; use crate::Foundation::NSValue; diff --git a/framework-crates/objc2-foundation/translation-config.toml b/framework-crates/objc2-foundation/translation-config.toml index e64b1c372..da63f9312 100644 --- a/framework-crates/objc2-foundation/translation-config.toml +++ b/framework-crates/objc2-foundation/translation-config.toml @@ -252,7 +252,7 @@ class.NSXPCCoder.methods."encodeXPCObject:forKey:".skipped = true class.NSXPCCoder.methods."decodeXPCObjectOfType:forKey:".skipped = true ### -### Mutability +### Counterparts ### class.NSArray.counterpart = "MutableSubclass(Foundation::NSArray::NSMutableArray)" @@ -267,18 +267,18 @@ class.NSMutableAttributedString.counterpart = "ImmutableSuperclass(Foundation::N class.NSData.counterpart = "MutableSubclass(Foundation::NSData::NSMutableData)" class.NSMutableData.counterpart = "ImmutableSuperclass(Foundation::NSData::NSData)" -# Auto traits and mutability can be deduced as if the dictionary was implemented as `(NSArray, NSArray)`. +# Auto traits can be deduced as if the dictionary was implemented as `(NSArray, NSArray)`. class.NSDictionary.counterpart = "MutableSubclass(Foundation::NSDictionary::NSMutableDictionary)" class.NSMutableDictionary.counterpart = "ImmutableSuperclass(Foundation::NSDictionary::NSDictionary)" -# Auto traits and mutability can be viewed as if the set was implemented with `NSArray`. +# Auto traits can be viewed as if the set was implemented with `NSArray`. class.NSSet.counterpart = "MutableSubclass(Foundation::NSSet::NSMutableSet)" class.NSMutableSet.counterpart = "ImmutableSuperclass(Foundation::NSSet::NSSet)" class.NSCharacterSet.counterpart = "MutableSubclass(Foundation::NSCharacterSet::NSMutableCharacterSet)" class.NSMutableCharacterSet.counterpart = "ImmutableSuperclass(Foundation::NSCharacterSet::NSCharacterSet)" -# Auto traits and mutability can be viewed as if the set was implemented with `NSArray`. +# Auto traits can be viewed as if the set was implemented with `NSArray`. class.NSOrderedSet.counterpart = "MutableSubclass(Foundation::NSOrderedSet::NSMutableOrderedSet)" class.NSMutableOrderedSet.counterpart = "ImmutableSuperclass(Foundation::NSOrderedSet::NSOrderedSet)" diff --git a/framework-crates/objc2-metal/examples/triangle.rs b/framework-crates/objc2-metal/examples/triangle.rs index 04808c188..19314d92a 100644 --- a/framework-crates/objc2-metal/examples/triangle.rs +++ b/framework-crates/objc2-metal/examples/triangle.rs @@ -3,10 +3,11 @@ use core::{cell::OnceCell, ptr::NonNull}; -use objc2::mutability::{IsMainThreadOnly, MainThreadOnly}; use objc2::rc::Retained; use objc2::runtime::ProtocolObject; -use objc2::{declare_class, msg_send_id, ClassType, DeclaredClass, MainThreadMarker}; +use objc2::{ + declare_class, msg_send_id, ClassType, DeclaredClass, MainThreadMarker, MainThreadOnly, +}; use objc2_app_kit::{ NSApplication, NSApplicationActivationPolicy, NSApplicationDelegate, NSBackingStoreType, NSWindow, NSWindowStyleMask, @@ -66,11 +67,11 @@ declare_class!( // SAFETY: // - The superclass NSObject does not have any subclassing requirements. - // - Main thread only mutability is correct, since this is an application delegate. + // - `MainThreadOnly` is correct, since this is an application delegate. // - `Delegate` does not implement `Drop`. unsafe impl ClassType for Delegate { type Super = NSObject; - type Mutability = MainThreadOnly; + type ThreadKind = dyn MainThreadOnly; const NAME: &'static str = "Delegate"; } @@ -96,7 +97,7 @@ declare_class!( let flag = false; unsafe { NSWindow::initWithContentRect_styleMask_backing_defer( - NSWindow::alloc_main_thread(mtm), + NSWindow::alloc(mtm), content_rect, style, backing_store_type, @@ -119,7 +120,9 @@ declare_class!( // create the metal view let mtk_view = { let frame_rect = window.frame(); - unsafe { MTKView::initWithFrame_device(MTKView::alloc_main_thread(mtm), frame_rect, Some(&device)) } + unsafe { + MTKView::initWithFrame_device(MTKView::alloc(mtm), frame_rect, Some(&device)) + } }; // create the pipeline descriptor @@ -280,7 +283,7 @@ declare_class!( impl Delegate { fn new(mtm: MainThreadMarker) -> Retained { - let this = Self::alloc_main_thread(mtm); + let this = Self::alloc(mtm); let this = this.set_ivars(Ivars { start_date: unsafe { NSDate::now() }, command_queue: OnceCell::default(), diff --git a/framework-crates/objc2-web-kit/examples/browser.rs b/framework-crates/objc2-web-kit/examples/browser.rs index 700d2548a..b8768f24b 100644 --- a/framework-crates/objc2-web-kit/examples/browser.rs +++ b/framework-crates/objc2-web-kit/examples/browser.rs @@ -4,10 +4,9 @@ use core::cell::OnceCell; use objc2::{ declare_class, msg_send_id, - mutability::{IsMainThreadOnly, MainThreadOnly}, rc::Retained, runtime::{AnyObject, ProtocolObject, Sel}, - sel, ClassType, DeclaredClass, MainThreadMarker, + sel, ClassType, DeclaredClass, MainThreadMarker, MainThreadOnly, }; #[allow(deprecated)] use objc2_app_kit::{ @@ -52,11 +51,11 @@ declare_class!( // SAFETY: // - The superclass NSObject does not have any subclassing requirements. - // - Main thread only mutability is correct, since this is an application delegate. + // - `MainThreadOnly` is correct, since this is an application delegate. // - `Delegate` does not implement `Drop`. unsafe impl ClassType for Delegate { type Super = NSObject; - type Mutability = MainThreadOnly; + type ThreadKind = dyn MainThreadOnly; const NAME: &'static str = "Delegate"; } @@ -81,7 +80,7 @@ declare_class!( let flag = false; unsafe { NSWindow::initWithContentRect_styleMask_backing_defer( - NSWindow::alloc_main_thread(mtm), + NSWindow::alloc(mtm), content_rect, style, backing_store_type, @@ -93,13 +92,13 @@ declare_class!( // create the web view let web_view = { let frame_rect = NSRect::ZERO; - unsafe { WKWebView::initWithFrame(WKWebView::alloc_main_thread(mtm), frame_rect) } + unsafe { WKWebView::initWithFrame(WKWebView::alloc(mtm), frame_rect) } }; // create the nav bar view let nav_bar = { let frame_rect = NSRect::ZERO; - let this = unsafe { NSStackView::initWithFrame(NSStackView::alloc_main_thread(mtm), frame_rect) }; + let this = unsafe { NSStackView::initWithFrame(NSStackView::alloc(mtm), frame_rect) }; unsafe { this.setOrientation(NSUserInterfaceLayoutOrientation::Horizontal); this.setAlignment(NSLayoutAttribute::Height); @@ -112,7 +111,7 @@ declare_class!( // create the nav buttons view let nav_buttons = { let frame_rect = NSRect::ZERO; - let this = unsafe { NSStackView::initWithFrame(NSStackView::alloc_main_thread(mtm), frame_rect) }; + let this = unsafe { NSStackView::initWithFrame(NSStackView::alloc(mtm), frame_rect) }; unsafe { this.setOrientation(NSUserInterfaceLayoutOrientation::Horizontal); this.setAlignment(NSLayoutAttribute::Height); @@ -160,7 +159,7 @@ declare_class!( // create the url text field let nav_url = { let frame_rect = NSRect::ZERO; - let this = unsafe { NSTextField::initWithFrame(NSTextField::alloc_main_thread(mtm), frame_rect) }; + let this = unsafe { NSTextField::initWithFrame(NSTextField::alloc(mtm), frame_rect) }; unsafe { this.setDrawsBackground(true); this.setBackgroundColor(Some(&NSColor::lightGrayColor())); @@ -177,7 +176,7 @@ declare_class!( // create the window content view let content_view = { let frame_rect = window.frame(); - let this = unsafe { NSStackView::initWithFrame(NSStackView::alloc_main_thread(mtm), frame_rect) }; + let this = unsafe { NSStackView::initWithFrame(NSStackView::alloc(mtm), frame_rect) }; unsafe { this.setOrientation(NSUserInterfaceLayoutOrientation::Vertical); this.setAlignment(NSLayoutAttribute::Width); @@ -204,14 +203,14 @@ declare_class!( // create the menu with a "quit" entry unsafe { - let menu = NSMenu::initWithTitle(NSMenu::alloc_main_thread(mtm), ns_string!("")); + let menu = NSMenu::initWithTitle(NSMenu::alloc(mtm), ns_string!("")); let menu_app_item = NSMenuItem::initWithTitle_action_keyEquivalent( - NSMenuItem::alloc_main_thread(mtm), + NSMenuItem::alloc(mtm), ns_string!(""), None, ns_string!(""), ); - let menu_app_menu = NSMenu::initWithTitle(NSMenu::alloc_main_thread(mtm), ns_string!("")); + let menu_app_menu = NSMenu::initWithTitle(NSMenu::alloc(mtm), ns_string!("")); menu_app_menu.addItemWithTitle_action_keyEquivalent( ns_string!("Quit"), Some(sel!(terminate:)), @@ -288,7 +287,7 @@ declare_class!( impl Delegate { fn new(mtm: MainThreadMarker) -> Retained { - let this = Self::alloc_main_thread(mtm); + let this = Self::alloc(mtm); let this = this.set_ivars(Ivars::default()); unsafe { msg_send_id![super(this), init] } } diff --git a/generated b/generated index ef8f5f110..ad3941dfb 160000 --- a/generated +++ b/generated @@ -1 +1 @@ -Subproject commit ef8f5f11053ba020ece249cc3c5c7749b9391086 +Subproject commit ad3941dfb176416ef4c85fd110478490693c8924