Skip to content

Commit 96412f0

Browse files
committed
Add unstable_extern_types feature
To see what changes we'd have to make in the library to use `extern type` (RFC-1861) (when it's is stabilized). Unfortunately had to change some usage of `ptr::null[_mut]` to `0 as *const/mut X`, see rust-lang/rust#42847.
1 parent 3e17c8b commit 96412f0

File tree

12 files changed

+38
-20
lines changed

12 files changed

+38
-20
lines changed

objc-sys/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ winobjc = ["gnustep-1-8"]
4747
# TODO
4848
objfw = []
4949

50+
# Marks opaque types as !Sized
51+
unstable_extern_types = []
52+
5053
[package.metadata.docs.rs]
5154
default-target = "x86_64-apple-darwin"
5255

objc-sys/src/lib.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//! [objc4-mirror]: https://github.com/madsmtm/objc4-mirror.git
1414
1515
#![no_std]
16+
#![cfg_attr(feature = "unstable_extern_types", feature(extern_types))]
1617
#![allow(clippy::upper_case_acronyms)]
1718
#![allow(non_camel_case_types)]
1819
#![allow(non_upper_case_globals)]
@@ -26,8 +27,11 @@
2627
// See https://github.com/japaric/cty/issues/14.
2728
extern crate std;
2829

29-
use core::cell::UnsafeCell;
30-
use core::marker::{PhantomData, PhantomPinned};
30+
#[cfg(not(feature = "unstable_extern_types"))]
31+
use core::{
32+
cell::UnsafeCell,
33+
marker::{PhantomData, PhantomPinned},
34+
};
3135

3236
mod class;
3337
mod constants;
@@ -63,4 +67,9 @@ pub use various::*;
6367
/// (It's also less of a breaking change on our part if we re-add these).
6468
///
6569
/// TODO: Replace this with `extern type` to also mark it as `!Sized`.
70+
#[cfg(not(feature = "unstable_extern_types"))]
6671
type OpaqueData = PhantomData<(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)>;
72+
#[cfg(feature = "unstable_extern_types")]
73+
extern "C" {
74+
type OpaqueData;
75+
}

objc2-foundation/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ default = ["block"]
2323
# Provided as a way to cut down on dependencies
2424
block = ["block2"]
2525

26+
unstable_extern_types = ["objc2/unstable_extern_types", "objc-sys/unstable_extern_types"]
27+
2628
[dependencies]
2729
# Exact dependencies, because block2 and objc2 are expected to change
2830
block2 = { path = "../block2", version = "=0.2.0-alpha.1", optional = true }

objc2-foundation/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![no_std]
2+
#![cfg_attr(feature = "unstable_extern_types", feature(extern_types))]
23
#![warn(elided_lifetimes_in_paths)]
34
#![deny(non_ascii_idents)]
45
#![warn(unreachable_pub)]

objc2/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ malloc = ["malloc_buf"]
3737

3838
# Uses nightly features to make AutoreleasePool zero-cost even in debug mode
3939
unstable_autoreleasesafe = []
40+
unstable_extern_types = ["objc-sys/unstable_extern_types"]
4041

4142
[dependencies]
4243
malloc_buf = { version = "1.0", optional = true }

objc2/src/cache.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ impl CachedSel {
3939
/// Allows storing a [`Class`] reference in a static and lazily loading it.
4040
#[doc(hidden)]
4141
pub struct CachedClass {
42-
ptr: AtomicPtr<Class>,
42+
ptr: AtomicPtr<c_void>,
4343
}
4444

4545
impl CachedClass {
@@ -56,7 +56,7 @@ impl CachedClass {
5656
#[doc(hidden)]
5757
pub unsafe fn get(&self, name: &str) -> Option<&'static Class> {
5858
// `Relaxed` should be fine since `objc_getClass` is thread-safe.
59-
let ptr = self.ptr.load(Ordering::Relaxed);
59+
let ptr = self.ptr.load(Ordering::Relaxed) as *const Class;
6060
if ptr.is_null() {
6161
let cls = unsafe { ffi::objc_getClass(name.as_ptr() as *const _) } as *const Class;
6262
self.ptr.store(cls as *mut _, Ordering::Relaxed);

objc2/src/declare.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ use alloc::format;
3636
use alloc::string::ToString;
3737
use core::mem;
3838
use core::mem::ManuallyDrop;
39-
use core::ptr;
4039
use std::ffi::CString;
4140

4241
use crate::runtime::{Bool, Class, Imp, Object, Protocol, Sel};
@@ -137,7 +136,7 @@ unsafe impl Sync for ClassDecl {}
137136
impl ClassDecl {
138137
fn with_superclass(name: &str, superclass: Option<&Class>) -> Option<ClassDecl> {
139138
let name = CString::new(name).unwrap();
140-
let super_ptr = superclass.map_or(ptr::null(), |c| c) as _;
139+
let super_ptr = superclass.map_or(0 as *const _, |c| c) as _;
141140
let cls = unsafe { ffi::objc_allocateClassPair(super_ptr, name.as_ptr(), 0) };
142141
if cls.is_null() {
143142
None

objc2/src/exception.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ extern "C" {
4545
pub unsafe fn throw(exception: Option<&Id<Object, Shared>>) -> ! {
4646
let exception = match exception {
4747
Some(id) => &**id as *const Object as *mut ffi::objc_object,
48-
None => ptr::null_mut(),
48+
None => ptr::from_raw_parts_mut(ptr::null_mut(), ()),
4949
};
5050
unsafe { ffi::objc_exception_throw(exception) }
5151
}
@@ -63,7 +63,7 @@ unsafe fn try_no_ret<F: FnOnce()>(closure: F) -> Result<(), Option<Id<Object, Sh
6363
let mut closure = Some(closure);
6464
let context = &mut closure as *mut _ as *mut c_void;
6565

66-
let mut exception = ptr::null_mut();
66+
let mut exception = ptr::from_raw_parts_mut(ptr::null_mut(), ());
6767
let success = unsafe { rust_objc_try_catch_exception(f, context, &mut exception) };
6868

6969
if success == 0 {

objc2/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ The bindings can be used on Linux or *BSD utilizing the
6363
feature = "unstable_autoreleasesafe",
6464
feature(negative_impls, auto_traits)
6565
)]
66+
#![cfg_attr(feature = "unstable_extern_types", feature(ptr_metadata))]
6667
#![warn(elided_lifetimes_in_paths)]
6768
#![warn(missing_docs)]
6869
#![deny(non_ascii_idents)]

objc2/src/message/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ mod tests {
399399
#[cfg(not(feature = "verify_message"))]
400400
#[test]
401401
fn test_send_message_nil() {
402-
let nil: *mut Object = ::core::ptr::null_mut();
402+
let nil: *mut Object = 0 as *mut Object;
403403

404404
let result: *mut Object = unsafe { msg_send![nil, description] };
405405
assert!(result.is_null());
@@ -447,7 +447,7 @@ mod tests {
447447
};
448448
assert_eq!(result, 4);
449449

450-
let obj: *const ManuallyDrop<Object> = (&**obj as *const Object).cast();
450+
let obj = &**obj as *const Object as *const ManuallyDrop<Object>;
451451
let result: u32 = unsafe { msg_send![obj, foo] };
452452
assert_eq!(result, 4);
453453
}

objc2/src/rc/weak_id.rs

+11-9
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub struct WeakId<T: ?Sized> {
3030
item: PhantomData<Id<T, Shared>>,
3131
}
3232

33-
impl<T: Message> WeakId<T> {
33+
impl<T: Message + ?Sized + ptr::Thin> WeakId<T> {
3434
/// Construct a new [`WeakId`] referencing the given shared [`Id`].
3535
#[doc(alias = "objc_initWeak")]
3636
pub fn new(obj: &Id<T, Shared>) -> Self {
@@ -45,7 +45,8 @@ impl<T: Message> WeakId<T> {
4545
///
4646
/// The object must be valid or null.
4747
unsafe fn new_inner(obj: *mut T) -> Self {
48-
let inner = Box::new(UnsafeCell::new(ptr::null_mut()));
48+
let null = ptr::from_raw_parts_mut(ptr::null_mut(), ());
49+
let inner = Box::new(UnsafeCell::new(null));
4950
// SAFETY: `ptr` will never move, and the caller verifies `obj`
5051
let _ = unsafe { ffi::objc_initWeak(inner.get() as _, obj as _) };
5152
Self {
@@ -64,7 +65,8 @@ impl<T: Message> WeakId<T> {
6465
#[inline]
6566
pub fn load(&self) -> Option<Id<T, Shared>> {
6667
let ptr: *mut *mut ffi::objc_object = self.inner.get() as _;
67-
let obj = unsafe { ffi::objc_loadWeakRetained(ptr) } as *mut T;
68+
let obj = unsafe { ffi::objc_loadWeakRetained(ptr) } as *mut ();
69+
let obj: *mut T = ptr::from_raw_parts_mut(obj, ());
6870
NonNull::new(obj).map(|obj| unsafe { Id::new(obj) })
6971
}
7072
}
@@ -77,12 +79,12 @@ impl<T: ?Sized> Drop for WeakId<T> {
7779
}
7880
}
7981

80-
// TODO: Add ?Sized
81-
impl<T> Clone for WeakId<T> {
82+
impl<T: ?Sized + ptr::Thin> Clone for WeakId<T> {
8283
/// Makes a clone of the `WeakId` that points to the same object.
8384
#[doc(alias = "objc_copyWeak")]
8485
fn clone(&self) -> Self {
85-
let ptr = Box::new(UnsafeCell::new(ptr::null_mut()));
86+
let null = ptr::from_raw_parts_mut(ptr::null_mut(), ());
87+
let ptr = Box::new(UnsafeCell::new(null));
8688
unsafe { ffi::objc_copyWeak(ptr.get() as _, self.inner.get() as _) };
8789
Self {
8890
inner: ptr,
@@ -91,14 +93,14 @@ impl<T> Clone for WeakId<T> {
9193
}
9294
}
9395

94-
// TODO: Add ?Sized
95-
impl<T: Message> Default for WeakId<T> {
96+
impl<T: Message + ?Sized + ptr::Thin> Default for WeakId<T> {
9697
/// Constructs a new `WeakId<T>` that doesn't reference any object.
9798
///
9899
/// Calling [`Self::load`] on the return value always gives [`None`].
99100
fn default() -> Self {
101+
let null = ptr::from_raw_parts_mut(ptr::null_mut(), ());
100102
// SAFETY: The pointer is null
101-
unsafe { Self::new_inner(ptr::null_mut()) }
103+
unsafe { Self::new_inner(null) }
102104
}
103105
}
104106

objc2/src/runtime.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ impl Class {
341341
let name = CString::new(name).unwrap();
342342
let ivar = unsafe { ffi::class_getClassVariable(self.as_ptr(), name.as_ptr()) };
343343
// SAFETY: TODO
344-
unsafe { ivar.cast::<Ivar>().as_ref() }
344+
unsafe { (ivar as *const Ivar).as_ref() }
345345
}
346346

347347
/// Describes the instance methods implemented by self.

0 commit comments

Comments
 (0)