From d5634ab013771bdd17cc45e03fb09b23bb6d7789 Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 15 Aug 2022 12:09:49 +0200 Subject: [PATCH 1/3] Rename ClassType::Superclass -> ClassType::Super And Id::into_superclass -> Id::into_super --- objc2/CHANGELOG.md | 2 +- objc2/examples/class_with_lifetime.rs | 4 ++-- objc2/examples/delegate.rs | 4 ++-- objc2/examples/nspasteboard.rs | 2 +- objc2/examples/speech_synthethis.rs | 6 +++--- objc2/src/class_type.rs | 8 ++++---- objc2/src/foundation/array.rs | 2 +- objc2/src/foundation/attributed_string.rs | 2 +- objc2/src/foundation/data.rs | 2 +- objc2/src/foundation/dictionary.rs | 2 +- objc2/src/foundation/error.rs | 2 +- objc2/src/foundation/exception.rs | 2 +- objc2/src/foundation/mod.rs | 4 ++-- objc2/src/foundation/mutable_array.rs | 2 +- .../foundation/mutable_attributed_string.rs | 2 +- objc2/src/foundation/mutable_data.rs | 2 +- objc2/src/foundation/mutable_string.rs | 2 +- objc2/src/foundation/number.rs | 2 +- objc2/src/foundation/object.rs | 2 +- objc2/src/foundation/process_info.rs | 2 +- objc2/src/foundation/string.rs | 2 +- objc2/src/foundation/thread.rs | 2 +- objc2/src/foundation/uuid.rs | 2 +- objc2/src/foundation/value.rs | 2 +- objc2/src/macros/declare_class.rs | 6 +++--- objc2/src/macros/extern_class.rs | 18 +++++++++--------- objc2/src/macros/extern_methods.rs | 4 ++-- objc2/src/rc/id.rs | 8 ++++---- objc2/src/rc/test_object.rs | 2 +- test-ui/ui/extern_class_not_zst.rs | 2 +- tests/src/test_object.rs | 2 +- 31 files changed, 53 insertions(+), 53 deletions(-) diff --git a/objc2/CHANGELOG.md b/objc2/CHANGELOG.md index 278418bfa..d21a55737 100644 --- a/objc2/CHANGELOG.md +++ b/objc2/CHANGELOG.md @@ -19,7 +19,7 @@ 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. ### Changed diff --git a/objc2/examples/class_with_lifetime.rs b/objc2/examples/class_with_lifetime.rs index 234ee41e2..a4001ce8f 100644 --- a/objc2/examples/class_with_lifetime.rs +++ b/objc2/examples/class_with_lifetime.rs @@ -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 @@ -125,7 +125,7 @@ fn main() { // It is not possible to convert to `Id` 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()); diff --git a/objc2/examples/delegate.rs b/objc2/examples/delegate.rs index 76db7f7ec..3fa877bae 100644 --- a/objc2/examples/delegate.rs +++ b/objc2/examples/delegate.rs @@ -13,7 +13,7 @@ extern_class!( struct NSResponder; unsafe impl ClassType for NSResponder { - type Superclass = NSObject; + type Super = NSObject; } ); @@ -26,7 +26,7 @@ declare_class!( unsafe impl ClassType for CustomAppDelegate { #[inherits(NSObject)] - type Superclass = NSResponder; + type Super = NSResponder; } unsafe impl CustomAppDelegate { diff --git a/objc2/examples/nspasteboard.rs b/objc2/examples/nspasteboard.rs index 42cea21c9..94c266e65 100644 --- a/objc2/examples/nspasteboard.rs +++ b/objc2/examples/nspasteboard.rs @@ -28,7 +28,7 @@ extern_class!( // SAFETY: NSPasteboard actually inherits from NSObject. unsafe impl ClassType for NSPasteboard { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/examples/speech_synthethis.rs b/objc2/examples/speech_synthethis.rs index 923a9ae47..d8d06c82d 100644 --- a/objc2/examples/speech_synthethis.rs +++ b/objc2/examples/speech_synthethis.rs @@ -31,7 +31,7 @@ mod appkit { pub struct NSSpeechSynthesizer; unsafe impl ClassType for NSSpeechSynthesizer { - type Superclass = NSObject; + type Super = NSObject; } ); @@ -110,7 +110,7 @@ mod avfaudio { pub struct AVSpeechSynthesizer; unsafe impl ClassType for AVSpeechSynthesizer { - type Superclass = NSObject; + type Super = NSObject; } ); @@ -136,7 +136,7 @@ mod avfaudio { pub struct AVSpeechUtterance; unsafe impl ClassType for AVSpeechUtterance { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/class_type.rs b/objc2/src/class_type.rs index 3b51004d5..4675c96e8 100644 --- a/objc2/src/class_type.rs +++ b/objc2/src/class_type.rs @@ -17,11 +17,11 @@ use crate::Message; /// # Safety /// /// The class returned by [`Self::class`] must be a subclass of the class that -/// [`Self::Superclass`] represents. +/// [`Self::Super`] represents. /// /// In pseudocode: /// ```ignore -/// Self::class().superclass() == ::class() +/// Self::class().superclass() == ::class() /// ``` /// /// @@ -48,7 +48,7 @@ use crate::Message; /// struct MyClass; /// /// unsafe impl ClassType for MyClass { -/// type Superclass = NSObject; +/// type Super = NSObject; /// } /// ); /// @@ -65,7 +65,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. /// diff --git a/objc2/src/foundation/array.rs b/objc2/src/foundation/array.rs index fbd5a6f32..4728952a0 100644 --- a/objc2/src/foundation/array.rs +++ b/objc2/src/foundation/array.rs @@ -58,7 +58,7 @@ __inner_extern_class!( } unsafe impl ClassType for NSArray { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/attributed_string.rs b/objc2/src/foundation/attributed_string.rs index dbac09f46..a8dee41db 100644 --- a/objc2/src/foundation/attributed_string.rs +++ b/objc2/src/foundation/attributed_string.rs @@ -25,7 +25,7 @@ extern_class!( pub struct NSAttributedString; unsafe impl ClassType for NSAttributedString { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/data.rs b/objc2/src/foundation/data.rs index b5f6f57c2..69ec8864a 100644 --- a/objc2/src/foundation/data.rs +++ b/objc2/src/foundation/data.rs @@ -21,7 +21,7 @@ extern_class!( pub struct NSData; unsafe impl ClassType for NSData { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/dictionary.rs b/objc2/src/foundation/dictionary.rs index 8ea7d1c2f..542d54a87 100644 --- a/objc2/src/foundation/dictionary.rs +++ b/objc2/src/foundation/dictionary.rs @@ -18,7 +18,7 @@ __inner_extern_class!( } unsafe impl ClassType for NSDictionary { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/error.rs b/objc2/src/foundation/error.rs index 372b395d9..bc62a8d5d 100644 --- a/objc2/src/foundation/error.rs +++ b/objc2/src/foundation/error.rs @@ -19,7 +19,7 @@ extern_class!( pub struct NSError; unsafe impl ClassType for NSError { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/exception.rs b/objc2/src/foundation/exception.rs index d88b544c1..2eac6c016 100644 --- a/objc2/src/foundation/exception.rs +++ b/objc2/src/foundation/exception.rs @@ -22,7 +22,7 @@ extern_class!( pub struct NSException; unsafe impl ClassType for NSException { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/mod.rs b/objc2/src/foundation/mod.rs index 3155524e9..faf186b86 100644 --- a/objc2/src/foundation/mod.rs +++ b/objc2/src/foundation/mod.rs @@ -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)] diff --git a/objc2/src/foundation/mutable_array.rs b/objc2/src/foundation/mutable_array.rs index 2ef97bccc..03273908a 100644 --- a/objc2/src/foundation/mutable_array.rs +++ b/objc2/src/foundation/mutable_array.rs @@ -27,7 +27,7 @@ __inner_extern_class!( unsafe impl ClassType for NSMutableArray { #[inherits(NSObject)] - type Superclass = NSArray; + type Super = NSArray; } ); diff --git a/objc2/src/foundation/mutable_attributed_string.rs b/objc2/src/foundation/mutable_attributed_string.rs index a3395d2c2..b8625e40d 100644 --- a/objc2/src/foundation/mutable_attributed_string.rs +++ b/objc2/src/foundation/mutable_attributed_string.rs @@ -13,7 +13,7 @@ extern_class!( unsafe impl ClassType for NSMutableAttributedString { #[inherits(NSObject)] - type Superclass = NSAttributedString; + type Super = NSAttributedString; } ); diff --git a/objc2/src/foundation/mutable_data.rs b/objc2/src/foundation/mutable_data.rs index c1735815c..e26caf1b0 100644 --- a/objc2/src/foundation/mutable_data.rs +++ b/objc2/src/foundation/mutable_data.rs @@ -24,7 +24,7 @@ extern_class!( unsafe impl ClassType for NSMutableData { #[inherits(NSObject)] - type Superclass = NSData; + type Super = NSData; } ); diff --git a/objc2/src/foundation/mutable_string.rs b/objc2/src/foundation/mutable_string.rs index ae647cbb2..135fc22fa 100644 --- a/objc2/src/foundation/mutable_string.rs +++ b/objc2/src/foundation/mutable_string.rs @@ -16,7 +16,7 @@ extern_class!( unsafe impl ClassType for NSMutableString { #[inherits(NSObject)] - type Superclass = NSString; + type Super = NSString; } ); diff --git a/objc2/src/foundation/number.rs b/objc2/src/foundation/number.rs index 170907359..c68e64cc2 100644 --- a/objc2/src/foundation/number.rs +++ b/objc2/src/foundation/number.rs @@ -43,7 +43,7 @@ extern_class!( unsafe impl ClassType for NSNumber { #[inherits(NSObject)] - type Superclass = NSValue; + type Super = NSValue; } ); diff --git a/objc2/src/foundation/object.rs b/objc2/src/foundation/object.rs index 141cc79eb..a4b382a44 100644 --- a/objc2/src/foundation/object.rs +++ b/objc2/src/foundation/object.rs @@ -16,7 +16,7 @@ __inner_extern_class! { } unsafe impl ClassType for NSObject { - type Superclass = Object; + type Super = Object; #[inline] fn class() -> &'static Class { diff --git a/objc2/src/foundation/process_info.rs b/objc2/src/foundation/process_info.rs index d3d1c3713..47b55c37b 100644 --- a/objc2/src/foundation/process_info.rs +++ b/objc2/src/foundation/process_info.rs @@ -13,7 +13,7 @@ extern_class!( pub struct NSProcessInfo; unsafe impl ClassType for NSProcessInfo { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/string.rs b/objc2/src/foundation/string.rs index fb2c29b54..d2f08599b 100644 --- a/objc2/src/foundation/string.rs +++ b/objc2/src/foundation/string.rs @@ -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; } ); diff --git a/objc2/src/foundation/thread.rs b/objc2/src/foundation/thread.rs index a95071d8e..e6bd609e1 100644 --- a/objc2/src/foundation/thread.rs +++ b/objc2/src/foundation/thread.rs @@ -14,7 +14,7 @@ extern_class!( pub struct NSThread; unsafe impl ClassType for NSThread { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/uuid.rs b/objc2/src/foundation/uuid.rs index eaf93e5a7..493f32e7b 100644 --- a/objc2/src/foundation/uuid.rs +++ b/objc2/src/foundation/uuid.rs @@ -20,7 +20,7 @@ extern_class!( pub struct NSUUID; unsafe impl ClassType for NSUUID { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/foundation/value.rs b/objc2/src/foundation/value.rs index aa32fc5c1..5ec29a638 100644 --- a/objc2/src/foundation/value.rs +++ b/objc2/src/foundation/value.rs @@ -35,7 +35,7 @@ extern_class!( pub struct NSValue; unsafe impl ClassType for NSValue { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/objc2/src/macros/declare_class.rs b/objc2/src/macros/declare_class.rs index c285644ef..a517ab1bc 100644 --- a/objc2/src/macros/declare_class.rs +++ b/objc2/src/macros/declare_class.rs @@ -246,7 +246,7 @@ macro_rules! __inner_declare_class { /// } /// /// unsafe impl ClassType for MyCustomObject { -/// type Superclass = NSObject; +/// type Super = NSObject; /// } /// /// unsafe impl MyCustomObject { @@ -383,7 +383,7 @@ macro_rules! declare_class { unsafe impl ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? - type Superclass = $superclass:ty; + type Super = $superclass:ty; } $($methods:tt)* @@ -420,7 +420,7 @@ macro_rules! declare_class { // Creation unsafe impl ClassType for $for { - type Superclass = $superclass; + type Super = $superclass; fn class() -> &'static $crate::runtime::Class { // TODO: Use `core::cell::LazyCell` diff --git a/objc2/src/macros/extern_class.rs b/objc2/src/macros/extern_class.rs index 475ad01fa..9cb8a724b 100644 --- a/objc2/src/macros/extern_class.rs +++ b/objc2/src/macros/extern_class.rs @@ -74,7 +74,7 @@ /// /// // Specify the superclass, in this case `NSObject` /// unsafe impl ClassType for NSFormatter { -/// type Superclass = NSObject; +/// type Super = NSObject; /// } /// ); /// @@ -97,7 +97,7 @@ /// # pub struct NSFormatter; /// # /// # unsafe impl ClassType for NSFormatter { -/// # type Superclass = NSObject; +/// # type Super = NSObject; /// # } /// # ); /// @@ -108,7 +108,7 @@ /// unsafe impl ClassType for NSDateFormatter { /// // Specify the correct inheritance chain /// #[inherits(NSObject)] -/// type Superclass = NSFormatter; +/// type Super = NSFormatter; /// } /// ); /// ``` @@ -123,7 +123,7 @@ macro_rules! extern_class { unsafe impl ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? - type Superclass = $superclass:ty; + type Super = $superclass:ty; } ) => { // Just shorthand syntax for the following @@ -133,7 +133,7 @@ macro_rules! extern_class { unsafe impl ClassType for $for { $(#[inherits($($inheritance_rest),+)])? - type Superclass = $superclass; + type Super = $superclass; } ); }; @@ -145,7 +145,7 @@ macro_rules! extern_class { unsafe impl ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? - type Superclass = $superclass:ty; + type Super = $superclass:ty; } ) => { $crate::__inner_extern_class!( @@ -156,7 +156,7 @@ macro_rules! extern_class { unsafe impl<> ClassType for $for { $(#[inherits($($inheritance_rest),+)])? - type Superclass = $superclass; + type Super = $superclass; } ); @@ -237,7 +237,7 @@ macro_rules! __inner_extern_class { unsafe impl<$($t_for:ident $(: $b_for:ident)?),*> ClassType for $for:ty { $(#[inherits($($inheritance_rest:ty),+)])? - type Superclass = $superclass:ty; + type Super = $superclass:ty; } ) => { $crate::__inner_extern_class! { @@ -253,7 +253,7 @@ macro_rules! __inner_extern_class { } unsafe impl<$($t_for $(: $b_for)?),*> ClassType for $for { - type Superclass = $superclass; + type Super = $superclass; #[inline] fn class() -> &'static $crate::runtime::Class { diff --git a/objc2/src/macros/extern_methods.rs b/objc2/src/macros/extern_methods.rs index d1a1a3508..1f090434b 100644 --- a/objc2/src/macros/extern_methods.rs +++ b/objc2/src/macros/extern_methods.rs @@ -50,7 +50,7 @@ /// pub struct NSCalendar; /// /// unsafe impl ClassType for NSCalendar { -/// type Superclass = NSObject; +/// type Super = NSObject; /// } /// ); /// @@ -130,7 +130,7 @@ /// # pub struct NSCalendar; /// # /// # unsafe impl ClassType for NSCalendar { -/// # type Superclass = NSObject; +/// # type Super = NSObject; /// # } /// # ); /// # diff --git a/objc2/src/rc/id.rs b/objc2/src/rc/id.rs index a64bd3356..4368593dc 100644 --- a/objc2/src/rc/id.rs +++ b/objc2/src/rc/id.rs @@ -266,7 +266,7 @@ impl Id { /// /// This is equivalent to a `cast` between two pointers. /// - /// See [`Id::into_superclass`] for a safe alternative. + /// See [`Id::into_super`] for a safe alternative. /// /// This is common to do when you know that an object is a subclass of /// a specific class (e.g. casting an instance of `NSString` to `NSObject` @@ -639,16 +639,16 @@ impl Id { impl Id where - T::Superclass: 'static, + T::Super: 'static, { /// Convert the object into it's superclass. #[inline] - pub fn into_superclass(this: Self) -> Id { + pub fn into_super(this: Self) -> Id { // SAFETY: // - The casted-to type is a superclass of the type. // - Both types are `'static` (this could maybe be relaxed a bit, but // let's just be on the safe side)! - unsafe { Self::cast::(this) } + unsafe { Self::cast::(this) } } } diff --git a/objc2/src/rc/test_object.rs b/objc2/src/rc/test_object.rs index 936430c3a..fff5b343e 100644 --- a/objc2/src/rc/test_object.rs +++ b/objc2/src/rc/test_object.rs @@ -55,7 +55,7 @@ declare_class!( pub(crate) struct RcTestObject {} unsafe impl ClassType for RcTestObject { - type Superclass = NSObject; + type Super = NSObject; } unsafe impl RcTestObject { diff --git a/test-ui/ui/extern_class_not_zst.rs b/test-ui/ui/extern_class_not_zst.rs index c9233171b..4addf2860 100644 --- a/test-ui/ui/extern_class_not_zst.rs +++ b/test-ui/ui/extern_class_not_zst.rs @@ -7,7 +7,7 @@ extern_class!( } unsafe impl ClassType for NSNumber { - type Superclass = NSObject; + type Super = NSObject; } ); diff --git a/tests/src/test_object.rs b/tests/src/test_object.rs index 14226cf52..02a466c73 100644 --- a/tests/src/test_object.rs +++ b/tests/src/test_object.rs @@ -21,7 +21,7 @@ unsafe impl RefEncode for MyTestObject { } unsafe impl ClassType for MyTestObject { - type Superclass = NSObject; + type Super = NSObject; fn class() -> &'static Class { class!(MyTestObject) From ace0604c5c496b9e032aaa70ff1a1a46164a38fa Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 15 Aug 2022 12:07:17 +0200 Subject: [PATCH 2/3] Add ClassType::as_super and ClassType::as_super_mut --- objc2/examples/class_with_lifetime.rs | 8 ++++++++ objc2/src/class_type.rs | 11 ++++++++++- objc2/src/foundation/object.rs | 8 ++++++++ objc2/src/macros/declare_class.rs | 10 ++++++++++ objc2/src/macros/extern_class.rs | 10 ++++++++++ tests/src/test_object.rs | 8 ++++++++ 6 files changed, 54 insertions(+), 1 deletion(-) diff --git a/objc2/examples/class_with_lifetime.rs b/objc2/examples/class_with_lifetime.rs index a4001ce8f..68657692b 100644 --- a/objc2/examples/class_with_lifetime.rs +++ b/objc2/examples/class_with_lifetime.rs @@ -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() { diff --git a/objc2/src/class_type.rs b/objc2/src/class_type.rs index 4675c96e8..c3166375b 100644 --- a/objc2/src/class_type.rs +++ b/objc2/src/class_type.rs @@ -17,7 +17,8 @@ use crate::Message; /// # Safety /// /// The class returned by [`Self::class`] must be a subclass of the class that -/// [`Self::Super`] represents. +/// [`Self::Super`] represents, and `as_super`/`as_super_mut` must be +/// implemented correctly. /// /// In pseudocode: /// ```ignore @@ -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; } diff --git a/objc2/src/foundation/object.rs b/objc2/src/foundation/object.rs index a4b382a44..39a77412f 100644 --- a/objc2/src/foundation/object.rs +++ b/objc2/src/foundation/object.rs @@ -22,6 +22,14 @@ unsafe impl ClassType for NSObject { 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!( diff --git a/objc2/src/macros/declare_class.rs b/objc2/src/macros/declare_class.rs index a517ab1bc..66e5e932e 100644 --- a/objc2/src/macros/declare_class.rs +++ b/objc2/src/macros/declare_class.rs @@ -454,6 +454,16 @@ macro_rules! declare_class { // We just registered the class, so it should be available $crate::runtime::Class::get(stringify!($name)).unwrap() } + + #[inline] + fn as_super(&self) -> &Self::Super { + &self.__inner + } + + #[inline] + fn as_super_mut(&mut self) -> &mut Self::Super { + &mut self.__inner + } } // Methods diff --git a/objc2/src/macros/extern_class.rs b/objc2/src/macros/extern_class.rs index 9cb8a724b..0ae77fcc7 100644 --- a/objc2/src/macros/extern_class.rs +++ b/objc2/src/macros/extern_class.rs @@ -259,6 +259,16 @@ macro_rules! __inner_extern_class { fn class() -> &'static $crate::runtime::Class { $crate::class!($name) } + + #[inline] + fn as_super(&self) -> &Self::Super { + &self.__inner + } + + #[inline] + fn as_super_mut(&mut self) -> &mut Self::Super { + &mut self.__inner + } } }; ( diff --git a/tests/src/test_object.rs b/tests/src/test_object.rs index 02a466c73..2484a78c8 100644 --- a/tests/src/test_object.rs +++ b/tests/src/test_object.rs @@ -26,6 +26,14 @@ unsafe impl ClassType for MyTestObject { fn class() -> &'static Class { class!(MyTestObject) } + + fn as_super(&self) -> &Self::Super { + &self.inner + } + + fn as_super_mut(&mut self) -> &mut Self::Super { + &mut self.inner + } } impl MyTestObject { From 7c8cfcc0e93721c91c811aa814b1e05c1439a1ac Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Mon, 15 Aug 2022 12:44:38 +0200 Subject: [PATCH 3/3] Allow omitting the superclass in `msg_send![super(...), ...]` Uses ClassType to get the superclass instead. --- objc2/CHANGELOG.md | 2 + objc2/examples/delegate.rs | 2 +- objc2/src/macros.rs | 60 +++++++++++++++++-- objc2/src/macros/declare_class.rs | 2 +- objc2/src/message/mod.rs | 43 ++++++++++++- objc2/src/rc/test_object.rs | 10 ++-- objc2/src/test_utils.rs | 6 ++ objc2/tests/no_prelude.rs | 8 ++- objc2/tests/use_macros.rs | 12 +++- test-ui/ui/invalid_msg_send_super.rs | 1 - test-ui/ui/invalid_msg_send_super.stderr | 6 -- test-ui/ui/msg_send_super_not_classtype.rs | 12 ++++ .../ui/msg_send_super_not_classtype.stderr | 45 ++++++++++++++ 13 files changed, 184 insertions(+), 25 deletions(-) create mode 100644 test-ui/ui/msg_send_super_not_classtype.rs create mode 100644 test-ui/ui/msg_send_super_not_classtype.stderr diff --git a/objc2/CHANGELOG.md b/objc2/CHANGELOG.md index d21a55737..3be91e20c 100644 --- a/objc2/CHANGELOG.md +++ b/objc2/CHANGELOG.md @@ -21,6 +21,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). `NSData::class()`. * 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. diff --git a/objc2/examples/delegate.rs b/objc2/examples/delegate.rs index 3fa877bae..d91c49289 100644 --- a/objc2/examples/delegate.rs +++ b/objc2/examples/delegate.rs @@ -32,7 +32,7 @@ declare_class!( 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; diff --git a/objc2/src/macros.rs b/objc2/src/macros.rs index 7a9d0c416..91ac32281 100644 --- a/objc2/src/macros.rs +++ b/objc2/src/macros.rs @@ -620,6 +620,10 @@ macro_rules! __class_inner { /// implements [`MessageReceiver`], like a reference or a pointer to an /// object, or even a reference to an [`rc::Id`] containing an object. /// +/// The expression can be wrapped in `super`, with an optional superclass +/// as the second argument. If no specific superclass is specified, the +/// direct superclass is retrieved from [`ClassType`]. +/// /// All arguments, and the return type, must implement [`Encode`]. /// /// This macro translates into a call to [`sel!`], and afterwards a fully @@ -633,6 +637,7 @@ macro_rules! __class_inner { /// /// [`MessageReceiver`]: crate::MessageReceiver /// [`rc::Id`]: crate::rc::Id +/// [`ClassType`]: crate::ClassType /// [`Encode`]: crate::Encode /// [`sel!`]: crate::sel /// [`MessageReceiver::send_message`]: crate::MessageReceiver::send_message @@ -691,25 +696,68 @@ macro_rules! __class_inner { /// /// # Examples /// +/// Sending messages to an object. +/// /// ```no_run -/// # use objc2::msg_send; -/// # use objc2::runtime::Object; +/// use objc2::msg_send; +/// use objc2::runtime::Object; +/// /// let obj: *mut Object; -/// # let obj: *mut Object = 0 as *mut Object; +/// # obj = 0 as *mut Object; /// let description: *const Object = unsafe { msg_send![obj, description] }; /// // Usually you'd use msg_send_id here ^ -/// let _: () = unsafe { msg_send![obj, setArg1: 1u32, arg2: 2i32] }; +/// let _: () = unsafe { msg_send![obj, setArg1: 1u32, arg2: 2u8] }; /// let arg1: i32 = unsafe { msg_send![obj, getArg1] }; -/// let arg2: i32 = unsafe { msg_send![obj, getArg2] }; +/// let arg2: u8 = unsafe { msg_send![obj, getArg2] }; +/// ``` +/// +/// Sending messages to the direct superclass of an object. +/// +/// ```no_run +/// use objc2::msg_send; +/// # use objc2::ns_string; +/// # use objc2::foundation::{NSString as MyObject}; +/// +/// let obj: &MyObject; // Some object that implements ClassType +/// # obj = ns_string!(""); +/// let _: () = unsafe { msg_send![super(obj), someMethod] }; +/// ``` +/// +/// Sending messages to a specific superclass of an object. +/// +/// ```no_run +/// # use objc2::class; +/// use objc2::msg_send; +/// use objc2::runtime::{Class, Object}; +/// +/// // Since we specify the superclass ourselves, this doesn't need to +/// // implement ClassType +/// let obj: *mut Object; +/// # obj = 0 as *mut Object; +/// let superclass: &Class; +/// # superclass = class!(NSObject); +/// let arg3: u32 = unsafe { msg_send![super(obj, superclass), getArg3] }; /// ``` #[macro_export] macro_rules! msg_send { - [super($obj:expr, $superclass:expr), $selector:ident $(,)?] => ({ + [super($obj:expr), $selector:ident $(,)?] => ({ let sel = $crate::sel!($selector); let result; // Note: `sel` and `result` can be accessed from the `obj` and // `superclass` expressions - we won't (yet) bother with preventing // that though. + result = $crate::MessageReceiver::__send_super_message_static($obj, sel, ()); + result + }); + [super($obj:expr), $($selector:ident : $argument:expr),+ $(,)?] => ({ + let sel = $crate::sel!($($selector :)+); + let result; + result = $crate::MessageReceiver::__send_super_message_static($obj, sel, ($($argument,)+)); + result + }); + [super($obj:expr, $superclass:expr), $selector:ident $(,)?] => ({ + let sel = $crate::sel!($selector); + let result; result = $crate::MessageReceiver::send_super_message($obj, $superclass, sel, ()); result }); diff --git a/objc2/src/macros/declare_class.rs b/objc2/src/macros/declare_class.rs index 66e5e932e..adca6263c 100644 --- a/objc2/src/macros/declare_class.rs +++ b/objc2/src/macros/declare_class.rs @@ -253,7 +253,7 @@ macro_rules! __inner_declare_class { /// #[sel(initWithFoo:)] /// fn init_with(&mut self, foo: u8) -> Option<&mut Self> { /// let this: Option<&mut Self> = unsafe { -/// msg_send![super(self, NSObject::class()), init] +/// msg_send![super(self), init] /// }; /// this.map(|this| { /// // TODO: Initialization through MaybeUninit diff --git a/objc2/src/message/mod.rs b/objc2/src/message/mod.rs index 0f53e6bff..b6c677f5c 100644 --- a/objc2/src/message/mod.rs +++ b/objc2/src/message/mod.rs @@ -4,7 +4,7 @@ use core::ptr::NonNull; use crate::rc::{Id, Owned, Ownership}; use crate::runtime::{Class, Imp, Object, Sel}; -use crate::{Encode, EncodeArguments, RefEncode}; +use crate::{ClassType, Encode, EncodeArguments, RefEncode}; #[cfg(feature = "catch-all")] #[track_caller] @@ -136,11 +136,15 @@ pub(crate) mod private { /// This is mostly an implementation detail; you'll want to implement /// [`Message`] for your type instead. /// +/// /// # Safety /// /// This is a sealed trait, and should not need to be implemented. Open an /// issue if you know a use-case where this restrition should be lifted! pub unsafe trait MessageReceiver: private::Sealed + Sized { + #[doc(hidden)] + type __Inner: ?Sized; + #[doc(hidden)] fn __as_raw_receiver(self) -> *mut Object; @@ -155,6 +159,7 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { /// /// [runtime]: https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc /// + /// /// # Safety /// /// This shares the same safety requirements as [`msg_send!`]. @@ -189,7 +194,7 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { unsafe { send_unverified(this, sel, args) } } - /// Sends a message to self's superclass with the given selector and + /// Sends a message to a specific superclass with the given selector and /// arguments. /// /// The correct version of `objc_msgSend_super` will be chosen based on the @@ -201,6 +206,7 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { /// /// [runtime]: https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc /// + /// /// # Safety /// /// This shares the same safety requirements as @@ -229,12 +235,27 @@ pub unsafe trait MessageReceiver: private::Sealed + Sized { } unsafe { send_super_unverified(this, superclass, sel, args) } } + + #[inline] + #[track_caller] + #[doc(hidden)] + unsafe fn __send_super_message_static(self, sel: Sel, args: A) -> R + where + Self::__Inner: ClassType, + ::Super: ClassType, + A: MessageArguments, + R: Encode, + { + unsafe { self.send_super_message(::Super::class(), sel, args) } + } } // Note that we implement MessageReceiver for unsized types as well, this is // to support `extern type`s in the future, not because we want to allow DSTs. unsafe impl MessageReceiver for *const T { + type __Inner = T; + #[inline] fn __as_raw_receiver(self) -> *mut Object { (self as *mut T).cast() @@ -242,6 +263,8 @@ unsafe impl MessageReceiver for *const T { } unsafe impl MessageReceiver for *mut T { + type __Inner = T; + #[inline] fn __as_raw_receiver(self) -> *mut Object { self.cast() @@ -249,6 +272,8 @@ unsafe impl MessageReceiver for *mut T { } unsafe impl MessageReceiver for NonNull { + type __Inner = T; + #[inline] fn __as_raw_receiver(self) -> *mut Object { self.as_ptr().cast() @@ -256,6 +281,8 @@ unsafe impl MessageReceiver for NonNull { } unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T { + type __Inner = T; + #[inline] fn __as_raw_receiver(self) -> *mut Object { let ptr: *const T = self; @@ -264,6 +291,8 @@ unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a T { } unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T { + type __Inner = T; + #[inline] fn __as_raw_receiver(self) -> *mut Object { let ptr: *mut T = self; @@ -272,6 +301,8 @@ unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut T { } unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a Id { + type __Inner = T; + #[inline] fn __as_raw_receiver(self) -> *mut Object { (Id::as_ptr(self) as *mut T).cast() @@ -279,6 +310,8 @@ unsafe impl<'a, T: Message + ?Sized, O: Ownership> MessageReceiver for &'a Id MessageReceiver for &'a mut Id { + type __Inner = T; + #[inline] fn __as_raw_receiver(self) -> *mut Object { Id::as_mut_ptr(self).cast() @@ -286,6 +319,8 @@ unsafe impl<'a, T: Message + ?Sized> MessageReceiver for &'a mut Id { } unsafe impl MessageReceiver for ManuallyDrop> { + type __Inner = T; + #[inline] fn __as_raw_receiver(self) -> *mut Object { Id::consume_as_ptr(self).cast() @@ -293,6 +328,8 @@ unsafe impl MessageReceiver for ManuallyDrop< } unsafe impl MessageReceiver for *const Class { + type __Inner = Class; + #[inline] fn __as_raw_receiver(self) -> *mut Object { (self as *mut Class).cast() @@ -300,6 +337,8 @@ unsafe impl MessageReceiver for *const Class { } unsafe impl<'a> MessageReceiver for &'a Class { + type __Inner = Class; + #[inline] fn __as_raw_receiver(self) -> *mut Object { let ptr: *const Class = self; diff --git a/objc2/src/rc/test_object.rs b/objc2/src/rc/test_object.rs index fff5b343e..948375b83 100644 --- a/objc2/src/rc/test_object.rs +++ b/objc2/src/rc/test_object.rs @@ -77,25 +77,25 @@ declare_class!( #[sel(init)] fn init(&mut self) -> *mut Self { TEST_DATA.with(|data| data.borrow_mut().init += 1); - unsafe { msg_send![super(self, NSObject::class()), init] } + unsafe { msg_send![super(self), init] } } #[sel(retain)] fn retain(&self) -> *mut Self { TEST_DATA.with(|data| data.borrow_mut().retain += 1); - unsafe { msg_send![super(self, NSObject::class()), retain] } + unsafe { msg_send![super(self), retain] } } #[sel(release)] fn release(&self) { TEST_DATA.with(|data| data.borrow_mut().release += 1); - unsafe { msg_send![super(self, NSObject::class()), release] } + unsafe { msg_send![super(self), release] } } #[sel(autorelease)] fn autorelease(&self) -> *mut Self { TEST_DATA.with(|data| data.borrow_mut().autorelease += 1); - unsafe { msg_send![super(self, NSObject::class()), autorelease] } + unsafe { msg_send![super(self), autorelease] } } #[sel(dealloc)] @@ -107,7 +107,7 @@ declare_class!( #[sel(_tryRetain)] unsafe fn try_retain(&self) -> Bool { TEST_DATA.with(|data| data.borrow_mut().try_retain += 1); - let res = unsafe { msg_send_bool![super(self, NSObject::class()), _tryRetain] }; + let res = unsafe { msg_send_bool![super(self), _tryRetain] }; if !res { TEST_DATA.with(|data| data.borrow_mut().try_retain -= 1); TEST_DATA.with(|data| data.borrow_mut().try_retain_fail += 1); diff --git a/objc2/src/test_utils.rs b/objc2/src/test_utils.rs index 1c71d73d2..d1c3688ca 100644 --- a/objc2/src/test_utils.rs +++ b/objc2/src/test_utils.rs @@ -27,6 +27,8 @@ impl crate::message::private::Sealed for &mut CustomObject {} impl crate::message::private::Sealed for ManuallyDrop {} unsafe impl MessageReceiver for &CustomObject { + type __Inner = Object; + #[inline] fn __as_raw_receiver(self) -> *mut Object { self.obj @@ -34,6 +36,8 @@ unsafe impl MessageReceiver for &CustomObject { } unsafe impl MessageReceiver for &mut CustomObject { + type __Inner = Object; + #[inline] fn __as_raw_receiver(self) -> *mut Object { self.obj @@ -41,6 +45,8 @@ unsafe impl MessageReceiver for &mut CustomObject { } unsafe impl MessageReceiver for ManuallyDrop { + type __Inner = Object; + #[inline] fn __as_raw_receiver(self) -> *mut Object { self.obj diff --git a/objc2/tests/no_prelude.rs b/objc2/tests/no_prelude.rs index 613340bfb..c950ab4f9 100644 --- a/objc2/tests/no_prelude.rs +++ b/objc2/tests/no_prelude.rs @@ -95,18 +95,22 @@ pub fn test_class() { let _class = new_objc2::class!(NSObject); } -pub fn test_msg_send(obj: &new_objc2::runtime::Object) { +pub fn test_msg_send(obj: &new_objc2::foundation::NSString) { let superclass = obj.class().superclass().unwrap(); let _: () = unsafe { new_objc2::msg_send![obj, a] }; let _: () = unsafe { new_objc2::msg_send![obj, a: obj, b: obj] }; + let _: () = unsafe { new_objc2::msg_send![super(obj), a] }; + let _: () = unsafe { new_objc2::msg_send![super(obj), a: obj, b: obj] }; let _: () = unsafe { new_objc2::msg_send![super(obj, superclass), a] }; let _: () = unsafe { new_objc2::msg_send![super(obj, superclass), a: obj, b: obj] }; } -pub fn test_msg_send_bool(obj: &new_objc2::runtime::Object) { +pub fn test_msg_send_bool(obj: &new_objc2::foundation::NSString) { let superclass = obj.class().superclass().unwrap(); unsafe { new_objc2::msg_send_bool![obj, a] }; unsafe { new_objc2::msg_send_bool![obj, a: obj, b: obj] }; + unsafe { new_objc2::msg_send_bool![super(obj), a] }; + unsafe { new_objc2::msg_send_bool![super(obj), a: obj, b: obj] }; unsafe { new_objc2::msg_send_bool![super(obj, superclass), a] }; unsafe { new_objc2::msg_send_bool![super(obj, superclass), a: obj, b: obj] }; } diff --git a/objc2/tests/use_macros.rs b/objc2/tests/use_macros.rs index b58ebe190..3f7c6418d 100644 --- a/objc2/tests/use_macros.rs +++ b/objc2/tests/use_macros.rs @@ -1,3 +1,4 @@ +use objc2::foundation::NSString; use objc2::runtime::{Class, Object}; use objc2::{class, msg_send, sel}; @@ -24,7 +25,7 @@ fn use_sel() { } #[allow(unused)] -fn test_msg_send_comma_handling(obj: &Object, superclass: &Class) { +fn test_msg_send_comma_handling(obj: &NSString, superclass: &Class) { unsafe { let _: () = msg_send![obj, a]; let _: () = msg_send![obj, a,]; @@ -46,4 +47,13 @@ fn test_msg_send_comma_handling(obj: &Object, superclass: &Class) { let _: () = msg_send![super(obj, superclass), a: 32i32, b: 32i32]; let _: () = msg_send![super(obj, superclass), a: 32i32, b: 32i32,]; } + + unsafe { + let _: () = msg_send![super(obj), a]; + let _: () = msg_send![super(obj), a,]; + let _: () = msg_send![super(obj), a: 32i32]; + let _: () = msg_send![super(obj), a: 32i32,]; + let _: () = msg_send![super(obj), a: 32i32, b: 32i32]; + let _: () = msg_send![super(obj), a: 32i32, b: 32i32,]; + } } diff --git a/test-ui/ui/invalid_msg_send_super.rs b/test-ui/ui/invalid_msg_send_super.rs index 8d83a5b74..ac406419b 100644 --- a/test-ui/ui/invalid_msg_send_super.rs +++ b/test-ui/ui/invalid_msg_send_super.rs @@ -8,7 +8,6 @@ fn main() { let _: () = unsafe { msg_send![super, init] }; let _: () = unsafe { msg_send![super(), init] }; - let _: () = unsafe { msg_send![super(obj), init] }; let _: () = unsafe { msg_send![super(obj,), init] }; let _: () = unsafe { msg_send![super(obj, superclass,), init] }; } diff --git a/test-ui/ui/invalid_msg_send_super.stderr b/test-ui/ui/invalid_msg_send_super.stderr index 0ec78ba31..f852d61bc 100644 --- a/test-ui/ui/invalid_msg_send_super.stderr +++ b/test-ui/ui/invalid_msg_send_super.stderr @@ -10,12 +10,6 @@ error[E0433]: failed to resolve: there are too many leading `super` keywords | let _: () = unsafe { msg_send![super(), init] }; | ^^^^^ there are too many leading `super` keywords -error[E0433]: failed to resolve: there are too many leading `super` keywords - --> ui/invalid_msg_send_super.rs - | - | let _: () = unsafe { msg_send![super(obj), init] }; - | ^^^^^ there are too many leading `super` keywords - error[E0433]: failed to resolve: there are too many leading `super` keywords --> ui/invalid_msg_send_super.rs | diff --git a/test-ui/ui/msg_send_super_not_classtype.rs b/test-ui/ui/msg_send_super_not_classtype.rs new file mode 100644 index 000000000..8adc7f449 --- /dev/null +++ b/test-ui/ui/msg_send_super_not_classtype.rs @@ -0,0 +1,12 @@ +//! Invalid receiver to msg_send![super(obj), ...], missing ClassType impl. +use objc2::msg_send; +use objc2::foundation::NSObject; +use objc2::runtime::Object; + +fn main() { + let obj: &Object; + let _: () = unsafe { msg_send![super(obj), method] }; + + let obj: &NSObject; // impls ClassType, but it's superclass does not + let _: () = unsafe { msg_send![super(obj), method] }; +} diff --git a/test-ui/ui/msg_send_super_not_classtype.stderr b/test-ui/ui/msg_send_super_not_classtype.stderr new file mode 100644 index 000000000..f56c680bd --- /dev/null +++ b/test-ui/ui/msg_send_super_not_classtype.stderr @@ -0,0 +1,45 @@ +error[E0277]: the trait bound `objc2::runtime::Object: ClassType` is not satisfied + --> ui/msg_send_super_not_classtype.rs + | + | let _: () = unsafe { msg_send![super(obj), method] }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ClassType` is not implemented for `objc2::runtime::Object` + | + = help: the following other types implement trait `ClassType`: + NSArray + NSAttributedString + NSData + NSDictionary + NSError + NSException + NSMutableArray + NSMutableAttributedString + and 9 others +note: required by a bound in `__send_super_message_static` + --> $WORKSPACE/objc2/src/message/mod.rs + | + | Self::__Inner: ClassType, + | ^^^^^^^^^ required by this bound in `__send_super_message_static` + = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0277]: the trait bound `objc2::runtime::Object: ClassType` is not satisfied + --> ui/msg_send_super_not_classtype.rs + | + | let _: () = unsafe { msg_send![super(obj), method] }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ClassType` is not implemented for `objc2::runtime::Object` + | + = help: the following other types implement trait `ClassType`: + NSArray + NSAttributedString + NSData + NSDictionary + NSError + NSException + NSMutableArray + NSMutableAttributedString + and 9 others +note: required by a bound in `__send_super_message_static` + --> $WORKSPACE/objc2/src/message/mod.rs + | + | ::Super: ClassType, + | ^^^^^^^^^ required by this bound in `__send_super_message_static` + = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)