From a897b422e60b9fa6d583f74ffa033a6c2728b948 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sat, 2 Sep 2023 01:09:49 +0200 Subject: [PATCH] Automatically determine MainThreadOnly ClassType::Mutability --- crates/header-translator/src/stmt.rs | 48 +++++++++++++------ crates/icrate/CHANGELOG.md | 19 +++++++- crates/icrate/examples/delegate.rs | 5 +- crates/icrate/src/common.rs | 4 +- crates/icrate/src/fixes/AppKit/mod.rs | 2 +- .../src/fixes/AuthenticationServices/mod.rs | 6 +-- crates/icrate/src/generated | 2 +- 7 files changed, 61 insertions(+), 25 deletions(-) diff --git a/crates/header-translator/src/stmt.rs b/crates/header-translator/src/stmt.rs index 7e79d700f..ff06650d3 100644 --- a/crates/header-translator/src/stmt.rs +++ b/crates/header-translator/src/stmt.rs @@ -306,7 +306,7 @@ pub enum Mutability { MutableWithImmutableSuperclass(ItemIdentifier), #[default] InteriorMutable, - // MainThreadOnly, + MainThreadOnly, } impl Mutability { @@ -330,6 +330,7 @@ impl fmt::Display for Mutability { write!(f, "MutableWithImmutableSuperclass<{}>", superclass.path()) } Self::InteriorMutable => write!(f, "InteriorMutable"), + Self::MainThreadOnly => write!(f, "MainThreadOnly"), } } } @@ -349,7 +350,6 @@ pub enum Stmt { mutability: Mutability, skipped: bool, sendable: bool, - mainthreadonly: bool, }, /// @interface class_name (name) /// -> @@ -565,7 +565,7 @@ impl Stmt { context, ); - let (sendable, mainthreadonly) = parse_attributes(entity, context); + let (sendable, mut mainthreadonly) = parse_attributes(entity, context); let mut protocols = Default::default(); parse_protocols(entity, &mut protocols, context); @@ -579,7 +579,17 @@ impl Stmt { let superclasses: Vec<_> = superclasses_full .iter() - .map(|(id, generics, _)| (id.clone(), generics.clone())) + .map(|(id, generics, entity)| { + // Ignore sendability on superclasses; because it's an auto trait, it's propagated to subclasses anyhow! + let (_sendable, superclass_mainthreadonly) = + parse_attributes(entity, context); + + if superclass_mainthreadonly { + mainthreadonly = true; + } + + (id.clone(), generics.clone()) + }) .collect(); // Used for duplicate checking (sometimes the subclass @@ -592,8 +602,6 @@ impl Stmt { .filter_map(|(superclass_id, _, entity)| { let superclass_data = context.class_data.get(&superclass_id.name); - // let (sendable, mainthreadonly) = parse_attributes(entity, context); - // Explicitly keep going, even if the class itself is skipped // if superclass_data.skipped @@ -647,10 +655,13 @@ impl Stmt { superclasses, designated_initializers, derives: data.map(|data| data.derives.clone()).unwrap_or_default(), - mutability: data.map(|data| data.mutability.clone()).unwrap_or_default(), + mutability: if mainthreadonly { + Mutability::MainThreadOnly + } else { + data.map(|data| data.mutability.clone()).unwrap_or_default() + }, skipped: data.map(|data| data.definition_skipped).unwrap_or_default(), sendable: sendable.unwrap_or(false), - mainthreadonly, }) .chain(protocols.into_iter().map(|protocol| Self::ProtocolImpl { cls: id.clone(), @@ -694,7 +705,7 @@ impl Stmt { ); let (sendable, mainthreadonly) = parse_attributes(entity, context); - if sendable.is_some() { + if let Some(sendable) = sendable { error!(?sendable, "sendable on category"); } if mainthreadonly { @@ -710,7 +721,18 @@ impl Stmt { let superclasses: Vec<_> = parse_superclasses(entity, context) .into_iter() - .map(|(id, generics, _)| (id, generics)) + .map(|(id, generics, entity)| { + let (sendable, mainthreadonly) = parse_attributes(&entity, context); + + if let Some(sendable) = sendable { + error!(?sendable, "sendable on category superclass"); + } + if mainthreadonly { + error!("@UIActor on category superclass"); + } + + (id, generics) + }) .collect(); let subclass_methods = if let Mutability::ImmutableWithMutableSubclass(subclass) = @@ -719,8 +741,6 @@ impl Stmt { let subclass_data = context.class_data.get(&subclass.name); assert!(!subclass_data.map(|data| data.skipped).unwrap_or_default()); - // let (sendable, mainthreadonly) = parse_attributes(entity, context); - let (mut methods, _) = parse_methods( entity, |name| { @@ -1320,7 +1340,6 @@ impl fmt::Display for Stmt { mutability, skipped, sendable, - mainthreadonly: _, } => { if *skipped { return Ok(()); @@ -1337,7 +1356,8 @@ impl fmt::Display for Stmt { Mutability::Immutable | Mutability::Mutable | Mutability::ImmutableWithMutableSubclass(_) - | Mutability::InteriorMutable => id.feature(), + | Mutability::InteriorMutable + | Mutability::MainThreadOnly => id.feature(), }; let (superclass, superclasses_rest) = superclasses.split_at(1); diff --git a/crates/icrate/CHANGELOG.md b/crates/icrate/CHANGELOG.md index dada78da5..f091fb1d2 100644 --- a/crates/icrate/CHANGELOG.md +++ b/crates/icrate/CHANGELOG.md @@ -19,9 +19,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). * Moved the `ns_string!` macro to `icrate::Foundation::ns_string`. The old location in the crate root is deprecated. * Use SDK from Xcode 14.3.1 (previously Xcode 14.2). -* **BREAKING**: The following two methods on `MTLAccelerationStructureCommandEncoder` now take a nullable scratch buffer: +* **BREAKING**: The following two methods on + `MTLAccelerationStructureCommandEncoder` now take a nullable scratch buffer: - `refitAccelerationStructure_descriptor_destination_scratchBuffer_scratchBufferOffset` - `refitAccelerationStructure_descriptor_destination_scratchBuffer_scratchBufferOffset_options` +* **BREAKING**: Marked UI-related types as `MainThreadOnly`. This means that + they can now only be constructed on the main thread, meaning you have to + aquire a `MainThreadMarker` first. + + ```rust + // Before + let app = unsafe { NSApplication::sharedApplication() }; + let view = unsafe { NSView::initWithFrame(NSView::alloc(), frame) }; + // Do something with `app` and `view` + + // After + let mtm = MainThreadMarker::new().unwrap(); + let app = unsafe { NSApplication::sharedApplication(mtm) }; + let view = unsafe { NSView::initWithFrame(mtm.alloc(), frame) }; + // Do something with `app` and `view` + ``` ### Removed * **BREAKING**: Removed the `MainThreadMarker` argument from the closure diff --git a/crates/icrate/examples/delegate.rs b/crates/icrate/examples/delegate.rs index 6f3bef426..5615e7f13 100644 --- a/crates/icrate/examples/delegate.rs +++ b/crates/icrate/examples/delegate.rs @@ -24,9 +24,8 @@ declare_class!( mod ivars; unsafe impl ClassType for AppDelegate { - #[inherits(NSObject)] - type Super = icrate::AppKit::NSResponder; - type Mutability = mutability::InteriorMutable; + type Super = NSObject; + type Mutability = mutability::MainThreadOnly; const NAME: &'static str = "MyAppDelegate"; } diff --git a/crates/icrate/src/common.rs b/crates/icrate/src/common.rs index fdc9fdaae..b6ba9c38f 100644 --- a/crates/icrate/src/common.rs +++ b/crates/icrate/src/common.rs @@ -14,8 +14,8 @@ pub(crate) use std::os::raw::{ pub(crate) use objc2::ffi::{NSInteger, NSIntegerMax, NSUInteger, NSUIntegerMax, IMP}; #[cfg(feature = "objective-c")] pub(crate) use objc2::mutability::{ - Immutable, ImmutableWithMutableSubclass, InteriorMutable, IsIdCloneable, Mutable, - MutableWithImmutableSuperclass, + Immutable, ImmutableWithMutableSubclass, InteriorMutable, IsIdCloneable, MainThreadOnly, + Mutable, MutableWithImmutableSuperclass, }; #[cfg(feature = "objective-c")] pub(crate) use objc2::rc::{Allocated, DefaultId, Id}; diff --git a/crates/icrate/src/fixes/AppKit/mod.rs b/crates/icrate/src/fixes/AppKit/mod.rs index a4c965482..44975eff4 100644 --- a/crates/icrate/src/fixes/AppKit/mod.rs +++ b/crates/icrate/src/fixes/AppKit/mod.rs @@ -36,7 +36,7 @@ extern_class!( unsafe impl ClassType for NSPopover { #[inherits(NSObject)] type Super = crate::AppKit::NSResponder; - type Mutability = InteriorMutable; + type Mutability = MainThreadOnly; } ); diff --git a/crates/icrate/src/fixes/AuthenticationServices/mod.rs b/crates/icrate/src/fixes/AuthenticationServices/mod.rs index 3de214181..26657c8f6 100644 --- a/crates/icrate/src/fixes/AuthenticationServices/mod.rs +++ b/crates/icrate/src/fixes/AuthenticationServices/mod.rs @@ -19,7 +19,7 @@ extern_class!( #[cfg(feature = "AuthenticationServices_ASCredentialProviderViewController")] unsafe impl ClassType for ASCredentialProviderViewController { type Super = ASViewController; - type Mutability = InteriorMutable; + type Mutability = MainThreadOnly; } ); @@ -31,7 +31,7 @@ extern_class!( #[cfg(feature = "AuthenticationServices_ASAccountAuthenticationModificationViewController")] unsafe impl ClassType for ASAccountAuthenticationModificationViewController { type Super = ASViewController; - type Mutability = InteriorMutable; + type Mutability = MainThreadOnly; } ); @@ -43,6 +43,6 @@ extern_class!( #[cfg(feature = "AuthenticationServices_ASAuthorizationAppleIDButton")] unsafe impl ClassType for ASAuthorizationAppleIDButton { type Super = ASControl; - type Mutability = InteriorMutable; + type Mutability = MainThreadOnly; } ); diff --git a/crates/icrate/src/generated b/crates/icrate/src/generated index bfe4ba4a9..7205d0e7b 160000 --- a/crates/icrate/src/generated +++ b/crates/icrate/src/generated @@ -1 +1 @@ -Subproject commit bfe4ba4a9871a46d1f9374854501b0a32eb608a6 +Subproject commit 7205d0e7bd68d94c0b6a4effddc7b746df7eae52