Skip to content

Commit a6308f2

Browse files
committed
Fix NS_SWIFT_SENDABLE protocols not being Send + Sync
This is especially relevant for Xcode 26, because they mark a lot of Metal APIs as sendable, and we would like that as well. #762
1 parent 520fcf2 commit a6308f2

File tree

6 files changed

+126
-18
lines changed

6 files changed

+126
-18
lines changed

crates/header-translator/src/stmt.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2586,7 +2586,7 @@ impl Stmt {
25862586
availability,
25872587
super_protocols,
25882588
methods,
2589-
required_sendable: _,
2589+
required_sendable,
25902590
required_mainthreadonly,
25912591
documentation,
25922592
} => {
@@ -2611,15 +2611,14 @@ impl Stmt {
26112611
write!(f, "{}", protocol.id.path())?;
26122612
}
26132613
}
2614-
// TODO
2615-
// if *required_sendable {
2616-
// if protocols.is_empty() {
2617-
// write!(f, ": ")?;
2618-
// } else {
2619-
// write!(f, "+ ")?;
2620-
// }
2621-
// write!(f, "Send + Sync")?;
2622-
// }
2614+
if *required_sendable {
2615+
if super_protocols.is_empty() {
2616+
write!(f, ": ")?;
2617+
} else {
2618+
write!(f, "+ ")?;
2619+
}
2620+
write!(f, "Send + Sync")?;
2621+
}
26232622
if *required_mainthreadonly {
26242623
if super_protocols.is_empty() {
26252624
write!(f, ": ")?;

crates/objc2/src/runtime/protocol_object.rs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,10 @@ mod tests {
208208

209209
use super::*;
210210
use crate::runtime::{ClassBuilder, NSObject};
211-
use crate::{define_class, extern_methods, extern_protocol, msg_send, ClassType};
211+
use crate::{
212+
define_class, extern_class, extern_conformance, extern_methods, extern_protocol, msg_send,
213+
ClassType,
214+
};
212215

213216
extern_protocol!(
214217
unsafe trait Foo {
@@ -258,10 +261,21 @@ mod tests {
258261
unsafe impl NSObjectProtocol for DummyClass {}
259262
);
260263

261-
unsafe impl Foo for DummyClass {}
262-
unsafe impl Bar for DummyClass {}
263-
unsafe impl FooBar for DummyClass {}
264-
// unsafe impl FooFooBar for DummyClass {}
264+
extern_conformance!(
265+
unsafe impl Foo for DummyClass {}
266+
);
267+
268+
extern_conformance!(
269+
unsafe impl Bar for DummyClass {}
270+
);
271+
272+
extern_conformance!(
273+
unsafe impl FooBar for DummyClass {}
274+
);
275+
276+
// extern_conformance!(
277+
// unsafe impl FooFooBar for DummyClass {}
278+
// );
265279

266280
impl DummyClass {
267281
extern_methods!(
@@ -410,4 +424,30 @@ mod tests {
410424
let expected = format!("<My\u{f8ff}êÄClass: {:p}>", &*obj);
411425
assert_eq!(format!("{obj:?}"), expected);
412426
}
427+
428+
#[test]
429+
fn send_sync() {
430+
extern_protocol!(
431+
#[name = "NSObject"]
432+
unsafe trait SendableProtocol: Send + Sync {}
433+
);
434+
435+
extern_class!(
436+
#[unsafe(super(NSObject))]
437+
#[name = "NSObject"]
438+
struct SendableObject;
439+
);
440+
441+
unsafe impl Send for SendableObject {}
442+
unsafe impl Sync for SendableObject {}
443+
444+
extern_conformance!(
445+
unsafe impl SendableProtocol for SendableObject {}
446+
);
447+
448+
assert_impl_all!(ProtocolObject<dyn SendableProtocol>: Send, Sync);
449+
450+
let obj: Retained<SendableObject> = unsafe { msg_send![SendableObject::class(), new] };
451+
let _proto: &ProtocolObject<dyn SendableProtocol> = ProtocolObject::from_ref(&*obj);
452+
}
413453
}

crates/objc2/src/topics/FRAMEWORKS_CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
4040
* **BREAKING**: Fixed structs with packed alignment by marking them `#[repr(packed(...))]`.
4141
* **BREAKING**: Fixed a few `MXMetricManager` methods that were instance methods instead of class methods.
4242
* Fixed missing deprecations on statics, type aliases and some impls blocks.
43+
* **BREAKING**: Fixed some protocols not being marked `Send + Sync` even when they should be.
44+
45+
This might break if you were implementing these yourself, in that case you should make your
46+
implementee `Send + Sync` as well.
4347

4448
## [0.3.1] - 2025-04-19
4549
[0.3.1]: https://github.com/madsmtm/objc2/compare/frameworks-0.3.0...frameworks-0.3.1

crates/test-ui/ui/implement_protocol_missing_super.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Test that implementing certain traits like `NSURLSessionDelegate` requires
2-
//! super protocols like `NSObjectProtocol` to also be implemented.
2+
//! super protocols like `NSObjectProtocol` and `Send + Sync` to also be
3+
//! implemented.
34
use objc2::{define_class, MainThreadOnly};
45
use objc2_foundation::{NSObject, NSURLSessionDelegate};
56

crates/test-ui/ui/implement_protocol_missing_super.stderr

Lines changed: 65 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)