Skip to content

Commit 09cd218

Browse files
committed
Make #[name = ...] attribute in define_class! optional
Part of #713.
1 parent 75bc9e7 commit 09cd218

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+98
-177
lines changed

crates/objc2/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
66

77
## Unreleased - YYYY-MM-DD
88

9+
## Added
10+
* Make `#[name = ...]` in `define_class!` optional. If not specified, the macro
11+
will choose a suitable default that makes loading multiple versions of the
12+
same library possible.
13+
914
## Fixed
1015
* Fixed undefined behaviour when calling `AnyObject::class` on invalid objects.
1116

crates/objc2/examples/hello_world_app.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ define_class!(
2525
// - `Delegate` does not implement `Drop`.
2626
#[unsafe(super = NSObject)]
2727
#[thread_kind = MainThreadOnly]
28-
#[name = "Delegate"]
2928
#[ivars = AppDelegateIvars]
3029
struct Delegate;
3130

crates/objc2/src/__macro_helpers/defined_ivars.rs

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,6 @@ mod tests {
499499

500500
define_class!(
501501
#[unsafe(super(NSObject))]
502-
#[name = "ImplsDrop"]
503502
#[ivars = ()]
504503
struct ImplsDrop;
505504

@@ -533,7 +532,6 @@ mod tests {
533532

534533
define_class!(
535534
#[unsafe(super(ImplsDrop))]
536-
#[name = "IvarsImplDrop"]
537535
#[ivars = IvarThatImplsDrop]
538536
struct IvarsImplDrop;
539537

@@ -561,7 +559,6 @@ mod tests {
561559

562560
define_class!(
563561
#[unsafe(super(IvarsImplDrop))]
564-
#[name = "BothIvarsAndTypeImplsDrop"]
565562
#[ivars = IvarThatImplsDrop]
566563
struct BothIvarsAndTypeImplsDrop;
567564

@@ -611,7 +608,6 @@ mod tests {
611608

612609
define_class!(
613610
#[unsafe(super(NSObject))]
614-
#[name = "IvarsNoDrop"]
615611
#[ivars = Ivar]
616612
struct IvarsNoDrop;
617613
);
@@ -631,7 +627,6 @@ mod tests {
631627

632628
define_class!(
633629
#[unsafe(super(NSObject))]
634-
#[name = "IvarZst"]
635630
#[ivars = Cell<Ivar>]
636631
struct IvarZst;
637632

@@ -694,7 +689,6 @@ mod tests {
694689
fn test_ivar_access() {
695690
define_class!(
696691
#[unsafe(super(NSObject))]
697-
#[name = "RcIvar"]
698692
#[ivars = Cell<Option<Retained<RcTestObject>>>]
699693
struct RcIvar;
700694

@@ -754,7 +748,6 @@ mod tests {
754748

755749
define_class!(
756750
#[unsafe(super(RcIvar))]
757-
#[name = "RcIvarSubclass"]
758751
#[ivars = RcIvarSubclassIvars]
759752
struct RcIvarSubclass;
760753

@@ -819,7 +812,6 @@ mod tests {
819812
fn access_invalid() {
820813
define_class!(
821814
#[unsafe(super(NSObject))]
822-
#[name = "InvalidAccess"]
823815
// Type has to have a drop flag to detect invalid access
824816
#[ivars = Retained<NSObject>]
825817
struct InvalidAccess;
@@ -836,7 +828,6 @@ mod tests {
836828
fn test_panic_in_drop() {
837829
define_class!(
838830
#[unsafe(super(NSObject))]
839-
#[name = "DropPanics"]
840831
struct DropPanics;
841832
);
842833

@@ -865,7 +856,6 @@ mod tests {
865856

866857
define_class!(
867858
#[unsafe(super(NSObject))]
868-
#[name = "IvarDropPanics"]
869859
#[ivars = DropPanics]
870860
struct IvarDropPanics;
871861
);
@@ -886,7 +876,6 @@ mod tests {
886876
define_class!(
887877
// SAFETY: Intentionally broken!
888878
#[unsafe(super(NSObject))]
889-
#[name = "DropRetainsAndLeaksSelf"]
890879
#[derive(Debug)]
891880
struct DropRetainsAndLeaksSelf;
892881
);

crates/objc2/src/__macro_helpers/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ pub use core::mem::{size_of, ManuallyDrop, MaybeUninit};
1010
pub use core::ops::Deref;
1111
pub use core::option::Option::{self, None, Some};
1212
pub use core::primitive::{bool, isize, str, u8};
13-
pub use core::{compile_error, concat, panic, stringify};
13+
pub use core::{compile_error, concat, env, module_path, panic, stringify};
1414
// TODO: Use `core::cell::LazyCell`
1515
pub use std::sync::Once;
1616

crates/objc2/src/__macro_helpers/msg_send_retained.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,6 @@ mod tests {
365365

366366
define_class!(
367367
#[unsafe(super(RcTestObject, NSObject))]
368-
#[name = "RcTestObjectSubclass"]
369368
#[derive(Debug, PartialEq, Eq)]
370369
struct RcTestObjectSubclass;
371370
);

crates/objc2/src/macros/define_class.rs

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,23 @@
6767
/// Same [as in `extern_class!`](crate::extern_class#thread_kind---optional).
6868
///
6969
///
70-
/// ### `#[name = "..."]` (required)
70+
/// ### `#[name = "..."]` (optional)
7171
///
72-
/// This is required, and must be unique across the entire application.
72+
/// Specify the runtime-name for the class. Must be unique across the entire
73+
/// application. This is useful if the name of a class is used elsewhere, such
74+
/// as when defining a delegate that needs to be named in e.g. `Info.plist`.
7375
///
74-
/// If you're developing a library, good practice here would be to include
75-
/// your crate name in the prefix (something like `"MyLibrary_MyClass"`).
76+
/// If not set, this will default to:
77+
/// ```ignore
78+
/// concat!(module_path!(), "::", $class, env!("CARGO_PKG_VERSION"));
79+
/// ```
80+
///
81+
/// E.g. for example `"my_crate::my_module::MyClass0.1.0"`.
82+
///
83+
/// If you're developing a library, it is recommended that you do not set
84+
/// this, and instead rely on the default naming, since that usually works
85+
/// better with users having multiple SemVer-incompatible versions of your
86+
/// library in the same binary.
7687
///
7788
///
7889
/// ### `#[ivars = ...]` (optional)
@@ -280,10 +291,16 @@
280291
/// // - The superclass NSObject does not have any subclassing requirements.
281292
/// // - `MyCustomObject` does not implement `Drop`.
282293
/// #[unsafe(super(NSObject))]
294+
///
283295
/// // If we were implementing delegate methods like `NSApplicationDelegate`,
284296
/// // we would specify the object to only be usable on the main thread:
285297
/// // #[thread_kind = MainThreadOnly]
286-
/// #[name = "MyCustomObject"]
298+
///
299+
/// // If we needed to refer to the class from elsewhere, we'd give it a
300+
/// // name here explicitly.
301+
/// // #[name = "MyCustomObject"]
302+
///
303+
/// // Specify the instance variables this class has.
287304
/// #[ivars = Ivars]
288305
/// struct MyCustomObject;
289306
///
@@ -565,7 +582,15 @@ macro_rules! __define_class_inner {
565582

566583
const NAME: &'static $crate::__macro_helpers::str = $crate::__fallback_if_not_set! {
567584
($($name)*)
568-
($crate::__macro_helpers::compile_error!("must set name of class with #[name = ...]"))
585+
(
586+
$crate::__macro_helpers::concat!(
587+
// Module path includes crate name when in library.
588+
$crate::__macro_helpers::module_path!(),
589+
"::",
590+
$crate::__macro_helpers::stringify!($class),
591+
$crate::__macro_helpers::env!("CARGO_PKG_VERSION"),
592+
)
593+
)
569594
};
570595

571596
fn class() -> &'static $crate::runtime::AnyClass {

crates/objc2/src/macros/extern_methods.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@
114114
/// // - The superclass NSObject does not have any subclassing requirements.
115115
/// // - `MyObject` does not implement `Drop`.
116116
/// #[unsafe(super(NSObject))]
117-
/// #[name = "MyObject"]
118117
/// pub struct MyObject;
119118
///
120119
/// impl MyObject {
@@ -171,7 +170,6 @@
171170
/// #
172171
/// # define_class!(
173172
/// # #[unsafe(super(NSObject))]
174-
/// # #[name = "MyObject2"]
175173
/// # pub struct MyObject;
176174
/// #
177175
/// # impl MyObject {

crates/objc2/src/macros/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,6 @@ macro_rules! __class_inner {
11041104
/// #
11051105
/// # objc2::define_class!(
11061106
/// # #[unsafe(super(NSObject))]
1107-
/// # #[name = "MyObject"]
11081107
/// # struct MyObject;
11091108
/// # );
11101109
/// #

crates/objc2/src/rc/retained_traits.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@ mod tests {
122122

123123
define_class!(
124124
#[unsafe(super(NSObject))]
125-
#[name = "MyCustomCollection"]
126125
#[derive(PartialEq, Eq, Hash, Debug)]
127126
struct Collection;
128127
);

crates/objc2/src/runtime/define.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,4 +1081,22 @@ mod tests {
10811081
//
10821082
// let ivar = *obj.get_ivar::<u8>("ivar3");
10831083
}
1084+
1085+
#[test]
1086+
fn auto_name() {
1087+
define_class!(
1088+
#[unsafe(super(NSObject))]
1089+
#[ivars = ()]
1090+
struct AutoName;
1091+
);
1092+
1093+
let expected = format!(
1094+
"objc2::runtime::define::tests::AutoName{}",
1095+
env!("CARGO_PKG_VERSION")
1096+
);
1097+
1098+
let cls = AutoName::class();
1099+
assert_eq!(cls.name().to_str().unwrap(), expected);
1100+
assert_eq!(AutoName::NAME, expected);
1101+
}
10841102
}

0 commit comments

Comments
 (0)