Skip to content

Commit a897b42

Browse files
committed
Automatically determine MainThreadOnly ClassType::Mutability
1 parent 78f9941 commit a897b42

File tree

7 files changed

+61
-25
lines changed

7 files changed

+61
-25
lines changed

crates/header-translator/src/stmt.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ pub enum Mutability {
306306
MutableWithImmutableSuperclass(ItemIdentifier),
307307
#[default]
308308
InteriorMutable,
309-
// MainThreadOnly,
309+
MainThreadOnly,
310310
}
311311

312312
impl Mutability {
@@ -330,6 +330,7 @@ impl fmt::Display for Mutability {
330330
write!(f, "MutableWithImmutableSuperclass<{}>", superclass.path())
331331
}
332332
Self::InteriorMutable => write!(f, "InteriorMutable"),
333+
Self::MainThreadOnly => write!(f, "MainThreadOnly"),
333334
}
334335
}
335336
}
@@ -349,7 +350,6 @@ pub enum Stmt {
349350
mutability: Mutability,
350351
skipped: bool,
351352
sendable: bool,
352-
mainthreadonly: bool,
353353
},
354354
/// @interface class_name (name) <protocols*>
355355
/// ->
@@ -565,7 +565,7 @@ impl Stmt {
565565
context,
566566
);
567567

568-
let (sendable, mainthreadonly) = parse_attributes(entity, context);
568+
let (sendable, mut mainthreadonly) = parse_attributes(entity, context);
569569

570570
let mut protocols = Default::default();
571571
parse_protocols(entity, &mut protocols, context);
@@ -579,7 +579,17 @@ impl Stmt {
579579

580580
let superclasses: Vec<_> = superclasses_full
581581
.iter()
582-
.map(|(id, generics, _)| (id.clone(), generics.clone()))
582+
.map(|(id, generics, entity)| {
583+
// Ignore sendability on superclasses; because it's an auto trait, it's propagated to subclasses anyhow!
584+
let (_sendable, superclass_mainthreadonly) =
585+
parse_attributes(entity, context);
586+
587+
if superclass_mainthreadonly {
588+
mainthreadonly = true;
589+
}
590+
591+
(id.clone(), generics.clone())
592+
})
583593
.collect();
584594

585595
// Used for duplicate checking (sometimes the subclass
@@ -592,8 +602,6 @@ impl Stmt {
592602
.filter_map(|(superclass_id, _, entity)| {
593603
let superclass_data = context.class_data.get(&superclass_id.name);
594604

595-
// let (sendable, mainthreadonly) = parse_attributes(entity, context);
596-
597605
// Explicitly keep going, even if the class itself is skipped
598606
// if superclass_data.skipped
599607

@@ -647,10 +655,13 @@ impl Stmt {
647655
superclasses,
648656
designated_initializers,
649657
derives: data.map(|data| data.derives.clone()).unwrap_or_default(),
650-
mutability: data.map(|data| data.mutability.clone()).unwrap_or_default(),
658+
mutability: if mainthreadonly {
659+
Mutability::MainThreadOnly
660+
} else {
661+
data.map(|data| data.mutability.clone()).unwrap_or_default()
662+
},
651663
skipped: data.map(|data| data.definition_skipped).unwrap_or_default(),
652664
sendable: sendable.unwrap_or(false),
653-
mainthreadonly,
654665
})
655666
.chain(protocols.into_iter().map(|protocol| Self::ProtocolImpl {
656667
cls: id.clone(),
@@ -694,7 +705,7 @@ impl Stmt {
694705
);
695706

696707
let (sendable, mainthreadonly) = parse_attributes(entity, context);
697-
if sendable.is_some() {
708+
if let Some(sendable) = sendable {
698709
error!(?sendable, "sendable on category");
699710
}
700711
if mainthreadonly {
@@ -710,7 +721,18 @@ impl Stmt {
710721

711722
let superclasses: Vec<_> = parse_superclasses(entity, context)
712723
.into_iter()
713-
.map(|(id, generics, _)| (id, generics))
724+
.map(|(id, generics, entity)| {
725+
let (sendable, mainthreadonly) = parse_attributes(&entity, context);
726+
727+
if let Some(sendable) = sendable {
728+
error!(?sendable, "sendable on category superclass");
729+
}
730+
if mainthreadonly {
731+
error!("@UIActor on category superclass");
732+
}
733+
734+
(id, generics)
735+
})
714736
.collect();
715737

716738
let subclass_methods = if let Mutability::ImmutableWithMutableSubclass(subclass) =
@@ -719,8 +741,6 @@ impl Stmt {
719741
let subclass_data = context.class_data.get(&subclass.name);
720742
assert!(!subclass_data.map(|data| data.skipped).unwrap_or_default());
721743

722-
// let (sendable, mainthreadonly) = parse_attributes(entity, context);
723-
724744
let (mut methods, _) = parse_methods(
725745
entity,
726746
|name| {
@@ -1320,7 +1340,6 @@ impl fmt::Display for Stmt {
13201340
mutability,
13211341
skipped,
13221342
sendable,
1323-
mainthreadonly: _,
13241343
} => {
13251344
if *skipped {
13261345
return Ok(());
@@ -1337,7 +1356,8 @@ impl fmt::Display for Stmt {
13371356
Mutability::Immutable
13381357
| Mutability::Mutable
13391358
| Mutability::ImmutableWithMutableSubclass(_)
1340-
| Mutability::InteriorMutable => id.feature(),
1359+
| Mutability::InteriorMutable
1360+
| Mutability::MainThreadOnly => id.feature(),
13411361
};
13421362

13431363
let (superclass, superclasses_rest) = superclasses.split_at(1);

crates/icrate/CHANGELOG.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1919
* Moved the `ns_string!` macro to `icrate::Foundation::ns_string`. The old
2020
location in the crate root is deprecated.
2121
* Use SDK from Xcode 14.3.1 (previously Xcode 14.2).
22-
* **BREAKING**: The following two methods on `MTLAccelerationStructureCommandEncoder` now take a nullable scratch buffer:
22+
* **BREAKING**: The following two methods on
23+
`MTLAccelerationStructureCommandEncoder` now take a nullable scratch buffer:
2324
- `refitAccelerationStructure_descriptor_destination_scratchBuffer_scratchBufferOffset`
2425
- `refitAccelerationStructure_descriptor_destination_scratchBuffer_scratchBufferOffset_options`
26+
* **BREAKING**: Marked UI-related types as `MainThreadOnly`. This means that
27+
they can now only be constructed on the main thread, meaning you have to
28+
aquire a `MainThreadMarker` first.
29+
30+
```rust
31+
// Before
32+
let app = unsafe { NSApplication::sharedApplication() };
33+
let view = unsafe { NSView::initWithFrame(NSView::alloc(), frame) };
34+
// Do something with `app` and `view`
35+
36+
// After
37+
let mtm = MainThreadMarker::new().unwrap();
38+
let app = unsafe { NSApplication::sharedApplication(mtm) };
39+
let view = unsafe { NSView::initWithFrame(mtm.alloc(), frame) };
40+
// Do something with `app` and `view`
41+
```
2542

2643
### Removed
2744
* **BREAKING**: Removed the `MainThreadMarker` argument from the closure

crates/icrate/examples/delegate.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ declare_class!(
2424
mod ivars;
2525

2626
unsafe impl ClassType for AppDelegate {
27-
#[inherits(NSObject)]
28-
type Super = icrate::AppKit::NSResponder;
29-
type Mutability = mutability::InteriorMutable;
27+
type Super = NSObject;
28+
type Mutability = mutability::MainThreadOnly;
3029
const NAME: &'static str = "MyAppDelegate";
3130
}
3231

crates/icrate/src/common.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ pub(crate) use std::os::raw::{
1414
pub(crate) use objc2::ffi::{NSInteger, NSIntegerMax, NSUInteger, NSUIntegerMax, IMP};
1515
#[cfg(feature = "objective-c")]
1616
pub(crate) use objc2::mutability::{
17-
Immutable, ImmutableWithMutableSubclass, InteriorMutable, IsIdCloneable, Mutable,
18-
MutableWithImmutableSuperclass,
17+
Immutable, ImmutableWithMutableSubclass, InteriorMutable, IsIdCloneable, MainThreadOnly,
18+
Mutable, MutableWithImmutableSuperclass,
1919
};
2020
#[cfg(feature = "objective-c")]
2121
pub(crate) use objc2::rc::{Allocated, DefaultId, Id};

crates/icrate/src/fixes/AppKit/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ extern_class!(
3636
unsafe impl ClassType for NSPopover {
3737
#[inherits(NSObject)]
3838
type Super = crate::AppKit::NSResponder;
39-
type Mutability = InteriorMutable;
39+
type Mutability = MainThreadOnly;
4040
}
4141
);
4242

crates/icrate/src/fixes/AuthenticationServices/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ extern_class!(
1919
#[cfg(feature = "AuthenticationServices_ASCredentialProviderViewController")]
2020
unsafe impl ClassType for ASCredentialProviderViewController {
2121
type Super = ASViewController;
22-
type Mutability = InteriorMutable;
22+
type Mutability = MainThreadOnly;
2323
}
2424
);
2525

@@ -31,7 +31,7 @@ extern_class!(
3131
#[cfg(feature = "AuthenticationServices_ASAccountAuthenticationModificationViewController")]
3232
unsafe impl ClassType for ASAccountAuthenticationModificationViewController {
3333
type Super = ASViewController;
34-
type Mutability = InteriorMutable;
34+
type Mutability = MainThreadOnly;
3535
}
3636
);
3737

@@ -43,6 +43,6 @@ extern_class!(
4343
#[cfg(feature = "AuthenticationServices_ASAuthorizationAppleIDButton")]
4444
unsafe impl ClassType for ASAuthorizationAppleIDButton {
4545
type Super = ASControl;
46-
type Mutability = InteriorMutable;
46+
type Mutability = MainThreadOnly;
4747
}
4848
);

crates/icrate/src/generated

0 commit comments

Comments
 (0)