Skip to content

Improve message sending to superclasses #243

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion objc2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
methods that `extern_class!` and `declare_class!` generated to that. This
means you'll have to `use objc2::ClassType` whenever you want to use e.g.
`NSData::class()`.
* Added `Id::into_superclass`.
* Added `Id::into_super`.
* Added `extern_methods!` macro.
* Added ability to call `msg_send![super(obj), ...]` without explicitly
specifying the superclass.

### Changed
* **BREAKING**: Change syntax in `extern_class!` macro to be more Rust-like.
Expand Down
12 changes: 10 additions & 2 deletions objc2/examples/class_with_lifetime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl<'a> MyObject<'a> {
}

unsafe impl<'a> ClassType for MyObject<'a> {
type Superclass = NSObject;
type Super = NSObject;

fn class() -> &'static Class {
// TODO: Use std::lazy::LazyCell
Expand Down Expand Up @@ -117,6 +117,14 @@ unsafe impl<'a> ClassType for MyObject<'a> {

Class::get("MyObject").unwrap()
}

fn as_super(&self) -> &Self::Super {
&self.superclass
}

fn as_super_mut(&mut self) -> &mut Self::Super {
&mut self.superclass
}
}

fn main() {
Expand All @@ -125,7 +133,7 @@ fn main() {

// It is not possible to convert to `Id<NSObject, Owned>` since that would
// loose the lifetime information that `MyObject` stores
// let obj = Id::into_superclass(obj);
// let obj = Id::into_super(obj);

println!("Number: {}", obj.get());

Expand Down
6 changes: 3 additions & 3 deletions objc2/examples/delegate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern_class!(
struct NSResponder;

unsafe impl ClassType for NSResponder {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand All @@ -26,13 +26,13 @@ declare_class!(

unsafe impl ClassType for CustomAppDelegate {
#[inherits(NSObject)]
type Superclass = NSResponder;
type Super = NSResponder;
}

unsafe impl CustomAppDelegate {
#[sel(initWith:another:)]
fn init_with(self: &mut Self, ivar: u8, another_ivar: Bool) -> *mut Self {
let this: *mut Self = unsafe { msg_send![super(self, NSResponder::class()), init] };
let this: *mut Self = unsafe { msg_send![super(self), init] };
if let Some(this) = unsafe { this.as_mut() } {
// TODO: Allow initialization through MaybeUninit
*this.ivar = ivar;
Expand Down
2 changes: 1 addition & 1 deletion objc2/examples/nspasteboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extern_class!(

// SAFETY: NSPasteboard actually inherits from NSObject.
unsafe impl ClassType for NSPasteboard {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
6 changes: 3 additions & 3 deletions objc2/examples/speech_synthethis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ mod appkit {
pub struct NSSpeechSynthesizer;

unsafe impl ClassType for NSSpeechSynthesizer {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down Expand Up @@ -110,7 +110,7 @@ mod avfaudio {
pub struct AVSpeechSynthesizer;

unsafe impl ClassType for AVSpeechSynthesizer {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand All @@ -136,7 +136,7 @@ mod avfaudio {
pub struct AVSpeechUtterance;

unsafe impl ClassType for AVSpeechUtterance {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
17 changes: 13 additions & 4 deletions objc2/src/class_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ use crate::Message;
/// # Safety
///
/// The class returned by [`Self::class`] must be a subclass of the class that
/// [`Self::Superclass`] represents.
/// [`Self::Super`] represents, and `as_super`/`as_super_mut` must be
/// implemented correctly.
///
/// In pseudocode:
/// ```ignore
/// Self::class().superclass() == <Self::Superclass as ClassType>::class()
/// Self::class().superclass() == <Self::Super as ClassType>::class()
/// ```
///
///
Expand All @@ -48,7 +49,7 @@ use crate::Message;
/// struct MyClass;
///
/// unsafe impl ClassType for MyClass {
/// type Superclass = NSObject;
/// type Super = NSObject;
/// }
/// );
///
Expand All @@ -65,7 +66,7 @@ pub unsafe trait ClassType: Message {
/// [`Deref`]: std::ops::Deref
/// [`Deref::Target`]: std::ops::Deref::Target
/// [`runtime::Object`]: crate::runtime::Object
type Superclass: Message;
type Super: Message;

/// Get a reference to the Objective-C class that this type represents.
///
Expand All @@ -78,4 +79,12 @@ pub unsafe trait ClassType: Message {
/// class, e.g. if the program is not properly linked to the framework
/// that defines the class.
fn class() -> &'static Class;

/// Get an immutable reference to the superclass.
// Note: It'd be safe to provide a default impl using transmute here if
// we wanted to!
fn as_super(&self) -> &Self::Super;

/// Get a mutable reference to the superclass.
fn as_super_mut(&mut self) -> &mut Self::Super;
}
2 changes: 1 addition & 1 deletion objc2/src/foundation/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ __inner_extern_class!(
}

unsafe impl<T: Message, O: Ownership> ClassType for NSArray<T, O> {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ extern_class!(
pub struct NSAttributedString;

unsafe impl ClassType for NSAttributedString {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ extern_class!(
pub struct NSData;

unsafe impl ClassType for NSData {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ __inner_extern_class!(
}

unsafe impl<K: Message, V: Message> ClassType for NSDictionary<K, V> {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ extern_class!(
pub struct NSError;

unsafe impl ClassType for NSError {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ extern_class!(
pub struct NSException;

unsafe impl ClassType for NSException {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
4 changes: 2 additions & 2 deletions objc2/src/foundation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@
//! want to use the objects!
//!
//! All objects also implement [`AsRef`] and [`AsMut`] to their superclass,
//! and can be used in [`Id::into_superclass`], so if you favour explicit
//! and can be used in [`Id::into_super`], so if you favour explicit
//! conversion, that is a possibility too.
//!
//! [`Deref`]: std::ops::Deref
//! [`ClassType`]: crate::ClassType
//! [anti-pattern-deref]: https://rust-unofficial.github.io/patterns/anti_patterns/deref.html
//! [`Id::into_superclass`]: crate::rc::Id::into_superclass
//! [`Id::into_super`]: crate::rc::Id::into_super

// TODO: Remove these
#![allow(missing_docs)]
Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/mutable_array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ __inner_extern_class!(

unsafe impl<T: Message, O: Ownership> ClassType for NSMutableArray<T, O> {
#[inherits(NSObject)]
type Superclass = NSArray<T, O>;
type Super = NSArray<T, O>;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/mutable_attributed_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern_class!(

unsafe impl ClassType for NSMutableAttributedString {
#[inherits(NSObject)]
type Superclass = NSAttributedString;
type Super = NSAttributedString;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/mutable_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ extern_class!(

unsafe impl ClassType for NSMutableData {
#[inherits(NSObject)]
type Superclass = NSData;
type Super = NSData;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/mutable_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extern_class!(

unsafe impl ClassType for NSMutableString {
#[inherits(NSObject)]
type Superclass = NSString;
type Super = NSString;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ extern_class!(

unsafe impl ClassType for NSNumber {
#[inherits(NSObject)]
type Superclass = NSValue;
type Super = NSValue;
}
);

Expand Down
10 changes: 9 additions & 1 deletion objc2/src/foundation/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ __inner_extern_class! {
}

unsafe impl ClassType for NSObject {
type Superclass = Object;
type Super = Object;

#[inline]
fn class() -> &'static Class {
class!(NSObject)
}

fn as_super(&self) -> &Self::Super {
&self.__inner
}

fn as_super_mut(&mut self) -> &mut Self::Super {
&mut self.__inner
}
}

extern_methods!(
Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/process_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern_class!(
pub struct NSProcessInfo;

unsafe impl ClassType for NSProcessInfo {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extern_class!(
// TODO: Check if performance of NSSelectorFromString is worthwhile

unsafe impl ClassType for NSString {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ extern_class!(
pub struct NSThread;

unsafe impl ClassType for NSThread {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/uuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ extern_class!(
pub struct NSUUID;

unsafe impl ClassType for NSUUID {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
2 changes: 1 addition & 1 deletion objc2/src/foundation/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ extern_class!(
pub struct NSValue;

unsafe impl ClassType for NSValue {
type Superclass = NSObject;
type Super = NSObject;
}
);

Expand Down
Loading