Skip to content

Commit 06e538a

Browse files
authored
Merge pull request #139 from madsmtm/various
Various improvements
2 parents 2a27f1c + a291ca2 commit 06e538a

File tree

20 files changed

+90
-83
lines changed

20 files changed

+90
-83
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ members = [
99
"tests",
1010
"tests/assembly/*",
1111
]
12+
resolver = "2"

block-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "block-sys"
33
version = "0.0.3" # Remember to update html_root_url in lib.rs
44
authors = ["Mads Marquart <[email protected]>"]
5-
edition = "2018"
5+
edition = "2021"
66

77
description = "Raw bindings to Apple's C language extension of blocks"
88
keywords = ["objective-c", "macos", "ios", "blocks", "sys"]

block2/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "block2"
33
# Remember to update html_root_url in lib.rs and README.md
44
version = "0.2.0-alpha.3"
55
authors = ["Steven Sheldon", "Mads Marquart <[email protected]>"]
6-
edition = "2018"
6+
edition = "2021"
77

88
description = "Apple's C language extension of blocks"
99
keywords = ["objective-c", "macos", "ios", "blocks"]

objc-sys/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "objc-sys"
33
version = "0.2.0-alpha.1" # Remember to update html_root_url in lib.rs
44
authors = ["Mads Marquart <[email protected]>"]
5-
edition = "2018"
5+
edition = "2021"
66

77
description = "Raw bindings to the Objective-C runtime and ABI"
88
keywords = ["objective-c", "macos", "ios", "objc_msgSend", "sys"]

objc-sys/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ and they act in slightly different ways. By default, Apple platforms link to
1818
Apple's runtime, but if you're using another runtime you must tell it to this
1919
library using feature flags.
2020

21+
One could ask, why even bother supporting other runtimes? To that, there's a
22+
simple answer: _Robustness_. By testing with these alternative runtimes in CI,
23+
we become by extension much more confident that our implementation doesn't
24+
rely on brittle unspecified behaviour, and works across different macOS and
25+
iOS versions.
26+
2127

2228
### Apple's [`objc4`](https://github.com/apple-oss-distributions/objc4)
2329

@@ -73,7 +79,7 @@ and `objc_autoreleasePoolPop` is a vital requirement for most applications.
7379

7480
Just so we're being clear, this rules out the GCC [`libobjc`][gcc-libobjc]
7581
runtime (see [this][gcc-objc-support]), the [`mulle-objc`] runtime and
76-
[cocotron]. (But support for [`ObjFW`] may be added).
82+
[cocotron]. (But support for [`ObjFW`] and [`darling`] may be added).
7783
More information on different runtimes can be found in GNUStep's
7884
[Objective-C Compiler and Runtime FAQ][gnustep-faq].
7985

@@ -83,6 +89,7 @@ More information on different runtimes can be found in GNUStep's
8389
[`mulle-objc`]: https://github.com/mulle-objc/mulle-objc-runtime
8490
[cocotron]: https://cocotron.org/
8591
[`ObjFW`]: https://github.com/ObjFW/ObjFW
92+
[`darling`]: https://github.com/darlinghq/darling-objc4
8693
[gnustep-faq]: http://wiki.gnustep.org/index.php/Objective-C_Compiler_and_Runtime_FAQ
8794

8895

objc2-encode/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name = "objc2-encode"
33
# Remember to update html_root_url in lib.rs and README.md
44
version = "2.0.0-beta.2"
55
authors = ["Steven Sheldon", "Mads Marquart <[email protected]>"]
6-
edition = "2018"
6+
edition = "2021"
77

88
description = "Objective-C type-encodings"
99
keywords = ["objective-c", "macos", "ios", "encode"]

objc2-foundation/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "objc2-foundation"
33
version = "0.2.0-alpha.4" # Remember to update html_root_url in lib.rs
44
authors = ["Steven Sheldon", "Mads Marquart <[email protected]>"]
5-
edition = "2018"
5+
edition = "2021"
66

77
description = "Bindings to the Objective-C Cocoa Foundation framework"
88
keywords = ["objective-c", "macos", "ios", "cocoa", "uikit"]

objc2/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name = "objc2"
33
version = "0.3.0-alpha.6" # Remember to update html_root_url in lib.rs
44
authors = ["Steven Sheldon", "Mads Marquart <[email protected]>"]
5-
edition = "2018"
5+
edition = "2021"
66

77
description = "Objective-C interface and runtime bindings"
88
keywords = ["objective-c", "macos", "ios", "objc_msgSend"]

objc2/examples/talk_to_me.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ extern "C" {}
1111
// Only works on macOS >= 10.15 or iOS > 7.0
1212
fn main() {
1313
let text = "Hello from Rust!";
14+
const UTF8_ENCODING: NSUInteger = 4;
1415

1516
let string: *const Object = unsafe { msg_send![class!(NSString), alloc] };
1617
let string = unsafe {
1718
msg_send![
1819
string,
1920
initWithBytes: text.as_ptr() as *const c_void,
2021
length: text.len(),
21-
encoding: 4 as NSUInteger, // UTF8_ENCODING on macOS / iOS
22+
encoding: UTF8_ENCODING,
2223
]
2324
};
2425
let string: Id<Object, Shared> = unsafe { Id::new(string).unwrap() };

objc2/src/declare.rs

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use alloc::string::ToString;
3939
use core::mem;
4040
use core::mem::ManuallyDrop;
4141
use core::ptr;
42+
use core::ptr::NonNull;
4243
use std::ffi::CString;
4344

4445
use crate::runtime::{Bool, Class, Imp, Object, Protocol, Sel};
@@ -120,7 +121,7 @@ fn log2_align_of<T>() -> u8 {
120121
/// before registering it.
121122
#[derive(Debug)]
122123
pub struct ClassDecl {
123-
cls: *mut Class,
124+
cls: NonNull<Class>,
124125
}
125126

126127
// SAFETY: The stuff that touch global state does so using locks internally.
@@ -138,23 +139,23 @@ unsafe impl Send for ClassDecl {}
138139
unsafe impl Sync for ClassDecl {}
139140

140141
impl ClassDecl {
141-
fn with_superclass(name: &str, superclass: Option<&Class>) -> Option<ClassDecl> {
142+
fn as_ptr(&self) -> *mut ffi::objc_class {
143+
self.cls.as_ptr().cast()
144+
}
145+
146+
fn with_superclass(name: &str, superclass: Option<&Class>) -> Option<Self> {
142147
let name = CString::new(name).unwrap();
143148
let super_ptr = superclass.map_or(ptr::null(), |c| c) as _;
144149
let cls = unsafe { ffi::objc_allocateClassPair(super_ptr, name.as_ptr(), 0) };
145-
if cls.is_null() {
146-
None
147-
} else {
148-
Some(ClassDecl { cls: cls as _ })
149-
}
150+
NonNull::new(cls.cast()).map(|cls| Self { cls })
150151
}
151152

152153
/// Constructs a [`ClassDecl`] with the given name and superclass.
153154
///
154155
/// Returns [`None`] if the class couldn't be allocated, or a class with
155156
/// that name already exist.
156-
pub fn new(name: &str, superclass: &Class) -> Option<ClassDecl> {
157-
ClassDecl::with_superclass(name, Some(superclass))
157+
pub fn new(name: &str, superclass: &Class) -> Option<Self> {
158+
Self::with_superclass(name, Some(superclass))
158159
}
159160

160161
/// Constructs a [`ClassDecl`] declaring a new root class with the given
@@ -171,12 +172,10 @@ impl ClassDecl {
171172
/// the entire `NSObject` protocol is implemented.
172173
/// Functionality it expects, like implementations of `-retain` and
173174
/// `-release` used by ARC, will not be present otherwise.
174-
pub fn root(name: &str, intitialize_fn: extern "C" fn(&Class, Sel)) -> Option<ClassDecl> {
175-
let mut decl = ClassDecl::with_superclass(name, None);
175+
pub fn root(name: &str, intitialize_fn: extern "C" fn(&Class, Sel)) -> Option<Self> {
176+
let mut decl = Self::with_superclass(name, None);
176177
if let Some(ref mut decl) = decl {
177-
unsafe {
178-
decl.add_class_method(sel!(initialize), intitialize_fn);
179-
}
178+
unsafe { decl.add_class_method(sel!(initialize), intitialize_fn) };
180179
}
181180
decl
182181
}
@@ -209,7 +208,7 @@ impl ClassDecl {
209208
let types = method_type_encoding(&F::Ret::ENCODING, encs);
210209
let success = Bool::from_raw(unsafe {
211210
ffi::class_addMethod(
212-
self.cls as _,
211+
self.as_ptr(),
213212
sel.as_ptr() as _,
214213
Some(func.imp()),
215214
types.as_ptr(),
@@ -244,7 +243,7 @@ impl ClassDecl {
244243
);
245244

246245
let types = method_type_encoding(&F::Ret::ENCODING, encs);
247-
let metaclass = unsafe { &*self.cls }.metaclass() as *const _ as *mut _;
246+
let metaclass = unsafe { self.cls.as_ref() }.metaclass() as *const _ as *mut _;
248247
let success = Bool::from_raw(unsafe {
249248
ffi::class_addMethod(
250249
metaclass,
@@ -268,7 +267,7 @@ impl ClassDecl {
268267
let align = log2_align_of::<T>();
269268
let success = Bool::from_raw(unsafe {
270269
ffi::class_addIvar(
271-
self.cls as _,
270+
self.as_ptr(),
272271
c_name.as_ptr(),
273272
size,
274273
align,
@@ -284,7 +283,7 @@ impl ClassDecl {
284283
///
285284
/// If the protocol wasn't successfully added.
286285
pub fn add_protocol(&mut self, proto: &Protocol) {
287-
let success = unsafe { ffi::class_addProtocol(self.cls as _, proto.as_ptr()) };
286+
let success = unsafe { ffi::class_addProtocol(self.as_ptr(), proto.as_ptr()) };
288287
let success = Bool::from_raw(success).as_bool();
289288
assert!(success, "Failed to add protocol {:?}", proto);
290289
}
@@ -296,40 +295,40 @@ impl ClassDecl {
296295
pub fn register(self) -> &'static Class {
297296
// Forget self, otherwise the class will be disposed in drop
298297
let cls = ManuallyDrop::new(self).cls;
299-
unsafe { ffi::objc_registerClassPair(cls as _) };
300-
unsafe { &*cls }
298+
unsafe { ffi::objc_registerClassPair(cls.as_ptr().cast()) };
299+
unsafe { cls.as_ref() }
301300
}
302301
}
303302

304303
impl Drop for ClassDecl {
305304
fn drop(&mut self) {
306-
unsafe { ffi::objc_disposeClassPair(self.cls as _) }
305+
unsafe { ffi::objc_disposeClassPair(self.as_ptr()) }
307306
}
308307
}
309308

310309
/// A type for declaring a new protocol and adding new methods to it
311310
/// before registering it.
312311
#[derive(Debug)]
313312
pub struct ProtocolDecl {
314-
proto: *mut Protocol,
313+
proto: NonNull<Protocol>,
315314
}
316315

317316
// SAFETY: Similar to ClassDecl
318317
unsafe impl Send for ProtocolDecl {}
319318
unsafe impl Sync for ProtocolDecl {}
320319

321320
impl ProtocolDecl {
321+
fn as_ptr(&self) -> *mut ffi::objc_protocol {
322+
self.proto.as_ptr().cast()
323+
}
324+
322325
/// Constructs a [`ProtocolDecl`] with the given name.
323326
///
324327
/// Returns [`None`] if the protocol couldn't be allocated.
325-
pub fn new(name: &str) -> Option<ProtocolDecl> {
328+
pub fn new(name: &str) -> Option<Self> {
326329
let c_name = CString::new(name).unwrap();
327330
let proto = unsafe { ffi::objc_allocateProtocol(c_name.as_ptr()) } as *mut Protocol;
328-
if proto.is_null() {
329-
None
330-
} else {
331-
Some(ProtocolDecl { proto })
332-
}
331+
NonNull::new(proto).map(|proto| Self { proto })
333332
}
334333

335334
fn add_method_description_common<Args, Ret>(
@@ -353,7 +352,7 @@ impl ProtocolDecl {
353352
let types = method_type_encoding(&Ret::ENCODING, encs);
354353
unsafe {
355354
ffi::protocol_addMethodDescription(
356-
self.proto as _,
355+
self.as_ptr(),
357356
sel.as_ptr() as _,
358357
types.as_ptr(),
359358
Bool::new(is_required).as_raw(),
@@ -383,16 +382,16 @@ impl ProtocolDecl {
383382
/// Adds a requirement on another protocol.
384383
pub fn add_protocol(&mut self, proto: &Protocol) {
385384
unsafe {
386-
ffi::protocol_addProtocol(self.proto as _, proto.as_ptr());
385+
ffi::protocol_addProtocol(self.as_ptr(), proto.as_ptr());
387386
}
388387
}
389388

390389
/// Registers the [`ProtocolDecl`], consuming it and returning a reference
391390
/// to the newly registered [`Protocol`].
392391
pub fn register(self) -> &'static Protocol {
393392
unsafe {
394-
ffi::objc_registerProtocol(self.proto as _);
395-
&*self.proto
393+
ffi::objc_registerProtocol(self.as_ptr());
394+
self.proto.as_ref()
396395
}
397396
}
398397
}

objc2/src/message/apple/arm.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use crate::{Encode, Encoding};
88
/// Double-word sized fundamental data types don't use stret, but any
99
/// composite type larger than 4 bytes does.
1010
///
11-
/// <http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf>
11+
/// <https://web.archive.org/web/20191016000656/http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf>
12+
/// <https://developer.arm.com/documentation/ihi0042/latest>
1213
unsafe impl<T: Encode> MsgSendFn for T {
1314
const MSG_SEND: Imp = {
1415
if let Encoding::LongLong | Encoding::ULongLong | Encoding::Double = T::ENCODING {

objc2/src/message/apple/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ mod arch;
1717

1818
/// On the above architectures we can statically find the correct method to
1919
/// call from the return type, by looking at it's `Encode` implementation.
20+
#[allow(clippy::missing_safety_doc)]
2021
unsafe trait MsgSendFn: Encode {
2122
const MSG_SEND: Imp;
2223
const MSG_SEND_SUPER: Imp;

objc2/src/message/apple/x86_64.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{Encode, Encoding};
99
/// MEMORY. If the type has class MEMORY, then the caller provides space for
1010
/// the return value and passes the address of this storage.
1111
///
12-
/// <http://people.freebsd.org/~obrien/amd64-elf-abi.pdf>
12+
/// <https://www.uclibc.org/docs/psABI-x86_64.pdf>
1313
unsafe impl<T: Encode> MsgSendFn for T {
1414
const MSG_SEND: Imp = {
1515
// See https://github.com/apple-oss-distributions/objc4/blob/objc4-818.2/runtime/message.h#L156-L172

objc2/src/message/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,9 @@ macro_rules! message_args_impl {
296296
let imp: unsafe extern "C" fn(*mut Object, Sel $(, $t)*) -> R = unsafe {
297297
mem::transmute(imp)
298298
};
299+
// TODO: On x86_64 it would be more efficient to use a GOT
300+
// entry here (e.g. adding `nonlazybind` in LLVM).
301+
// Same can be said of e.g. `objc_retain` and `objc_release`.
299302
unsafe { imp(obj, sel $(, $a)*) }
300303
}
301304
}

objc2/src/rc/id.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,13 @@ impl<T: Message, O: Ownership> Id<T, O> {
312312
{
313313
// Supported since macOS 10.7.
314314
#[cfg(target_arch = "x86_64")]
315-
{} // x86_64 looks at the next call instruction
315+
{
316+
// x86_64 looks at the next call instruction.
317+
//
318+
// This is expected to be a PLT entry - if the user specifies
319+
// `-Zplt=no`, a GOT entry will be created instead, and this
320+
// will not work.
321+
}
316322

317323
// Supported since macOS 10.8.
318324
#[cfg(target_arch = "arm")]
@@ -350,7 +356,7 @@ impl<T: Message, O: Ownership> Id<T, O> {
350356
{
351357
// SAFETY: Similar to above.
352358
unsafe { core::arch::asm!("nop", options(nomem, preserves_flags, nostack)) };
353-
// TODO: Possibly more efficient alternative?
359+
// TODO: Possibly more efficient alternative? Also consider PLT.
354360
// #![feature(asm_sym)]
355361
// core::arch::asm!(
356362
// "mov rdi, rax",

objc2/src/rc/weak_id.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use alloc::boxed::Box;
22
use core::cell::UnsafeCell;
3-
use core::convert::TryFrom;
43
use core::fmt;
54
use core::marker::PhantomData;
65
use core::ptr;
@@ -145,7 +144,7 @@ impl<T: Message> From<Id<T, Shared>> for WeakId<T> {
145144
impl<T: Message> TryFrom<WeakId<T>> for Id<T, Shared> {
146145
type Error = ();
147146
fn try_from(weak: WeakId<T>) -> Result<Self, ()> {
148-
return weak.load().ok_or(());
147+
weak.load().ok_or(())
149148
}
150149
}
151150

0 commit comments

Comments
 (0)