Skip to content

Commit

Permalink
Change declare_class! syntax
Browse files Browse the repository at this point in the history
This follows the similar change to extern_class! in b8c24dc.

Fixes #479.
Fixes #555.
Part of #267.
  • Loading branch information
madsmtm committed Nov 26, 2024
1 parent 0fe2de1 commit 0494d07
Show file tree
Hide file tree
Showing 53 changed files with 954 additions and 1,046 deletions.
29 changes: 10 additions & 19 deletions crates/objc2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
subclassing `NSObject`.

### 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.
* **BREAKING**: Changed the syntax of `declare_class!` to be more succinct:

```rust
// Before
Expand All @@ -49,32 +47,25 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
}

impl DeclaredClass for MyObject {
type Ivars = ...;
type Ivars = MyIvars;
}

// ...
// unsafe impl ...
);

// After
declare_class!(
#[unsafe(super(NSObject))]
#[name = "MyObject"]
#[ivars = MyIvars]
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 = ...;
}

// ...
// unsafe impl ...
);
```
* Whether classes are only available on the main thread is now automatically
inferred, and you only need to overwrite it if your class is doing something
different than its superclass.
* **BREAKING**: Changed the syntax of `extern_class!` to be more succinct:
```rust
// Before
Expand Down
142 changes: 36 additions & 106 deletions crates/objc2/src/__macro_helpers/declared_ivars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,17 +497,11 @@ mod tests {
// First class

declare_class!(
#[unsafe(super(NSObject))]
#[name = "ImplsDrop"]
#[ivars = ()]
struct ImplsDrop;

unsafe impl ClassType for ImplsDrop {
type Super = NSObject;
const NAME: &'static str = "ImplsDrop";
}

impl DeclaredClass for ImplsDrop {
type Ivars = ();
}

unsafe impl ImplsDrop {
#[method_id(init)]
fn init(this: Allocated<Self>) -> Option<Retained<Self>> {
Expand Down Expand Up @@ -537,17 +531,11 @@ mod tests {
// Subclass

declare_class!(
#[unsafe(super(ImplsDrop))]
#[name = "IvarsImplDrop"]
#[ivars = IvarThatImplsDrop]
struct IvarsImplDrop;

unsafe impl ClassType for IvarsImplDrop {
type Super = ImplsDrop;
const NAME: &'static str = "IvarsImplDrop";
}

impl DeclaredClass for IvarsImplDrop {
type Ivars = IvarThatImplsDrop;
}

unsafe impl IvarsImplDrop {
#[method_id(init)]
fn init(this: Allocated<Self>) -> Option<Retained<Self>> {
Expand All @@ -571,17 +559,11 @@ mod tests {
// Further subclass

declare_class!(
#[unsafe(super(IvarsImplDrop))]
#[name = "BothIvarsAndTypeImplsDrop"]
#[ivars = IvarThatImplsDrop]
struct BothIvarsAndTypeImplsDrop;

unsafe impl ClassType for BothIvarsAndTypeImplsDrop {
type Super = IvarsImplDrop;
const NAME: &'static str = "BothIvarsAndTypeImplsDrop";
}

impl DeclaredClass for BothIvarsAndTypeImplsDrop {
type Ivars = IvarThatImplsDrop;
}

unsafe impl BothIvarsAndTypeImplsDrop {
#[method_id(init)]
fn init(this: Allocated<Self>) -> Option<Retained<Self>> {
Expand Down Expand Up @@ -627,16 +609,10 @@ mod tests {
}

declare_class!(
#[unsafe(super(NSObject))]
#[name = "IvarsNoDrop"]
#[ivars = Ivar]
struct IvarsNoDrop;

unsafe impl ClassType for IvarsNoDrop {
type Super = NSObject;
const NAME: &'static str = "IvarsNoDrop";
}

impl DeclaredClass for IvarsNoDrop {
type Ivars = Ivar;
}
);

assert!(!mem::needs_drop::<IvarsNoDrop>());
Expand All @@ -653,17 +629,11 @@ mod tests {
struct Ivar;

declare_class!(
#[unsafe(super(NSObject))]
#[name = "IvarZst"]
#[ivars = Cell<Ivar>]
struct IvarZst;

unsafe impl ClassType for IvarZst {
type Super = NSObject;
const NAME: &'static str = "IvarZst";
}

impl DeclaredClass for IvarZst {
type Ivars = Cell<Ivar>;
}

unsafe impl IvarZst {
#[method_id(init)]
fn init(this: Allocated<Self>) -> Option<Retained<Self>> {
Expand Down Expand Up @@ -697,16 +667,10 @@ mod tests {
struct HighAlignment;

declare_class!(
#[unsafe(super(NSObject))]
#[name = "HasIvarWithHighAlignment"]
#[ivars = HighAlignment]
struct HasIvarWithHighAlignment;

unsafe impl ClassType for HasIvarWithHighAlignment {
type Super = NSObject;
const NAME: &'static str = "HasIvarWithHighAlignment";
}

impl DeclaredClass for HasIvarWithHighAlignment {
type Ivars = HighAlignment;
}
);

// Have to allocate up to the desired alignment, but no need to go
Expand All @@ -728,17 +692,11 @@ mod tests {
#[test]
fn test_ivar_access() {
declare_class!(
#[unsafe(super(NSObject))]
#[name = "RcIvar"]
#[ivars = Cell<Option<Retained<RcTestObject>>>]
struct RcIvar;

unsafe impl ClassType for RcIvar {
type Super = NSObject;
const NAME: &'static str = "RcIvar";
}

impl DeclaredClass for RcIvar {
type Ivars = Cell<Option<Retained<RcTestObject>>>;
}

unsafe impl RcIvar {
#[method_id(init)]
fn init(this: Allocated<Self>) -> Option<Retained<Self>> {
Expand Down Expand Up @@ -794,17 +752,11 @@ mod tests {
}

declare_class!(
#[unsafe(super(RcIvar))]
#[name = "RcIvarSubclass"]
#[ivars = RcIvarSubclassIvars]
struct RcIvarSubclass;

unsafe impl ClassType for RcIvarSubclass {
type Super = RcIvar;
const NAME: &'static str = "RcIvarSubclass";
}

impl DeclaredClass for RcIvarSubclass {
type Ivars = RcIvarSubclassIvars;
}

unsafe impl RcIvarSubclass {
#[method_id(init)]
fn init(this: Allocated<Self>) -> Option<Retained<Self>> {
Expand Down Expand Up @@ -865,17 +817,11 @@ mod tests {
#[should_panic = "tried to access uninitialized instance variable"]
fn access_invalid() {
declare_class!(
#[unsafe(super(NSObject))]
#[name = "InvalidAccess"]
// Type has to have a drop flag to detect invalid access
#[ivars = Retained<NSObject>]
struct InvalidAccess;

unsafe impl ClassType for InvalidAccess {
type Super = NSObject;
const NAME: &'static str = "InvalidAccess";
}

impl DeclaredClass for InvalidAccess {
// Type has to have a drop flag to detect invalid access
type Ivars = Retained<NSObject>;
}
);

let obj = unsafe { init_only_superclasses(InvalidAccess::alloc()) };
Expand All @@ -888,14 +834,9 @@ mod tests {
#[ignore = "panicking in Drop requires that we actually implement `dealloc` as `C-unwind`"]
fn test_panic_in_drop() {
declare_class!(
#[unsafe(super(NSObject))]
#[name = "DropPanics"]
struct DropPanics;

unsafe impl ClassType for DropPanics {
type Super = NSObject;
const NAME: &'static str = "DropPanics";
}

impl DeclaredClass for DropPanics {}
);

impl Drop for DropPanics {
Expand All @@ -922,16 +863,10 @@ mod tests {
}

declare_class!(
#[unsafe(super(NSObject))]
#[name = "IvarDropPanics"]
#[ivars = DropPanics]
struct IvarDropPanics;

unsafe impl ClassType for IvarDropPanics {
type Super = NSObject;
const NAME: &'static str = "IvarDropPanics";
}

impl DeclaredClass for IvarDropPanics {
type Ivars = DropPanics;
}
);

let obj = IvarDropPanics::alloc().set_ivars(DropPanics);
Expand All @@ -948,16 +883,11 @@ mod tests {
#[test]
fn test_retain_leak_in_drop() {
declare_class!(
// SAFETY: Intentionally broken!
#[unsafe(super(NSObject))]
#[name = "DropRetainsAndLeaksSelf"]
#[derive(Debug)]
struct DropRetainsAndLeaksSelf;

// SAFETY: Intentionally broken!
unsafe impl ClassType for DropRetainsAndLeaksSelf {
type Super = NSObject;
const NAME: &'static str = "DropRetainsAndLeaksSelf";
}

impl DeclaredClass for DropRetainsAndLeaksSelf {}
);

unsafe impl Send for DropRetainsAndLeaksSelf {}
Expand Down
12 changes: 3 additions & 9 deletions crates/objc2/src/__macro_helpers/msg_send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ impl<T: ?Sized + Message> MsgSend for ManuallyDrop<Retained<T>> {
mod tests {
use crate::rc::{autoreleasepool, RcTestObject, ThreadTestData};
use crate::runtime::NSObject;
use crate::{declare_class, msg_send, msg_send_id, test_utils, ClassType, DeclaredClass};
use crate::{declare_class, msg_send, msg_send_id, test_utils};

use super::*;

Expand Down Expand Up @@ -230,16 +230,10 @@ mod tests {
}

declare_class!(
#[unsafe(super(RcTestObject, NSObject))]
#[name = "RcTestObjectSubclass"]
#[derive(Debug, PartialEq, Eq)]
struct RcTestObjectSubclass;

unsafe impl ClassType for RcTestObjectSubclass {
#[inherits(NSObject)]
type Super = RcTestObject;
const NAME: &'static str = "RcTestObjectSubclass";
}

impl DeclaredClass for RcTestObjectSubclass {}
);

#[cfg_attr(not(test), allow(unused))]
Expand Down
Loading

0 comments on commit 0494d07

Please sign in to comment.