Skip to content

Commit 2a23ed9

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 dc303e6 commit 2a23ed9

File tree

17 files changed

+76
-44
lines changed

17 files changed

+76
-44
lines changed

objc-sys/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,6 @@ readme = "README.md"
2727
# See https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts
2828
links = "objc"
2929
build = "build.rs"
30+
31+
[features]
32+
unstable_extern_types = []

objc-sys/src/lib.rs

Lines changed: 11 additions & 2 deletions
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;
@@ -61,4 +65,9 @@ pub use various::*;
6165
/// also less of a breaking change on our part if we re-add these later).
6266
///
6367
/// TODO: Replace this with `extern type` to also mark it as unsized.
68+
#[cfg(not(feature = "unstable_extern_types"))]
6469
type OpaqueData = PhantomData<(UnsafeCell<*const ()>, PhantomPinned)>;
70+
#[cfg(feature = "unstable_extern_types")]
71+
extern "C" {
72+
type OpaqueData;
73+
}

objc2-foundation/Cargo.toml

Lines changed: 2 additions & 0 deletions
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
block2 = { path = "../block2", optional = true }
2830
objc2 = { path = "../objc2" }

objc2-foundation/src/array.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ unsafe fn from_refs<A: INSArray + ?Sized>(refs: &[&A::Item]) -> Id<A, A::Ownersh
2929
}
3030

3131
pub unsafe trait INSArray: INSObject {
32-
type Item: INSObject;
32+
type Item: INSObject + ?Sized;
3333
type ItemOwnership: Ownership;
3434

3535
unsafe_def_fn!(fn new);
@@ -165,13 +165,17 @@ pub unsafe trait INSArray: INSObject {
165165
///
166166
/// `Id<NSArray<T, Owned>, Shared>` is possible, but pretty useless.
167167
/// TODO: Can we make it impossible? Should we?
168-
pub struct NSArray<T, O: Ownership> {
168+
pub struct NSArray<T: ?Sized, O: Ownership> {
169169
item: PhantomData<Id<T, O>>,
170170
}
171171

172-
object_impl!(unsafe NSArray<T, O: Ownership>);
172+
unsafe impl<T: ?Sized, O: Ownership> objc2::Message for NSArray<T, O> {}
173173

174-
unsafe impl<T: INSObject, O: Ownership> INSObject for NSArray<T, O> {
174+
unsafe impl<T: ?Sized, O: Ownership> objc2::RefEncode for NSArray<T, O> {
175+
const ENCODING_REF: objc2::Encoding<'static> = objc2::Encoding::Object;
176+
}
177+
178+
unsafe impl<T: INSObject + ?Sized, O: Ownership> INSObject for NSArray<T, O> {
175179
/// The `NSArray` itself (length and number of items) is always immutable,
176180
/// but we would like to know when we're the only owner of the array, to
177181
/// allow mutation of the array's items.
@@ -184,14 +188,14 @@ unsafe impl<T: INSObject, O: Ownership> INSObject for NSArray<T, O> {
184188
}
185189
}
186190

187-
unsafe impl<T: INSObject, O: Ownership> INSArray for NSArray<T, O> {
191+
unsafe impl<T: INSObject + ?Sized, O: Ownership> INSArray for NSArray<T, O> {
188192
type Item = T;
189193
type ItemOwnership = O;
190194
}
191195

192196
// Copying only possible when ItemOwnership = Shared
193197

194-
unsafe impl<T: INSObject> INSCopying for NSArray<T, Shared> {
198+
unsafe impl<T: INSObject + ?Sized> INSCopying for NSArray<T, Shared> {
195199
type Output = NSArray<T, Shared>;
196200
}
197201

objc2-foundation/src/copying.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub unsafe trait INSCopying: INSObject {
1515
/// // would be able to create aliasing mutable references!
1616
/// let y: Id<MyObject, Owned> = x.copy();
1717
/// ```
18-
type Output: INSObject;
18+
type Output: INSObject + ?Sized;
1919

2020
fn copy(&self) -> Id<Self::Output, <Self::Output as INSObject>::Ownership> {
2121
unsafe {
@@ -28,7 +28,7 @@ pub unsafe trait INSCopying: INSObject {
2828
pub unsafe trait INSMutableCopying: INSObject {
2929
/// An [`Owned`] [`INSObject`] is required to be able to return an owned
3030
/// [`Id`].
31-
type Output: INSObject<Ownership = Owned>;
31+
type Output: INSObject<Ownership = Owned> + ?Sized;
3232

3333
fn mutable_copy(&self) -> Id<Self::Output, Owned> {
3434
unsafe {

objc2-foundation/src/dictionary.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ where
3131
}
3232

3333
pub unsafe trait INSDictionary: INSObject {
34-
type Key: INSObject;
35-
type Value: INSObject;
34+
type Key: INSObject + ?Sized;
35+
type Value: INSObject + ?Sized;
3636
type ValueOwnership: Ownership;
3737

3838
unsafe_def_fn!(fn new);
@@ -141,32 +141,38 @@ pub unsafe trait INSDictionary: INSObject {
141141
}
142142
}
143143

144-
pub struct NSDictionary<K, V> {
144+
pub struct NSDictionary<K: ?Sized, V: ?Sized> {
145145
key: PhantomData<Id<K, Shared>>,
146146
obj: PhantomData<Id<V, Owned>>,
147147
}
148148

149-
object_impl!(unsafe NSDictionary<K, V>);
149+
unsafe impl<K: ?Sized, V: ?Sized> ::objc2::Message for NSDictionary<K, V> {}
150150

151-
unsafe impl<K: INSObject, V: INSObject> INSObject for NSDictionary<K, V> {
151+
unsafe impl<K: ?Sized, V: ?Sized> ::objc2::RefEncode for NSDictionary<K, V> {
152+
const ENCODING_REF: objc2::Encoding<'static> = objc2::Encoding::Object;
153+
}
154+
155+
unsafe impl<K: INSObject + ?Sized, V: INSObject + ?Sized> INSObject for NSDictionary<K, V> {
152156
type Ownership = Shared;
153157

154158
fn class() -> &'static Class {
155159
class!(NSDictionary)
156160
}
157161
}
158162

159-
unsafe impl<K: INSObject, V: INSObject> INSDictionary for NSDictionary<K, V> {
163+
unsafe impl<K: INSObject + ?Sized, V: INSObject + ?Sized> INSDictionary for NSDictionary<K, V> {
160164
type Key = K;
161165
type Value = V;
162166
type ValueOwnership = Owned;
163167
}
164168

165-
unsafe impl<K: INSObject, V: INSObject> INSFastEnumeration for NSDictionary<K, V> {
169+
unsafe impl<K: INSObject + ?Sized, V: INSObject + ?Sized> INSFastEnumeration
170+
for NSDictionary<K, V>
171+
{
166172
type Item = K;
167173
}
168174

169-
impl<'a, K: INSObject, V: INSObject> Index<&'a K> for NSDictionary<K, V> {
175+
impl<'a, K: INSObject + ?Sized, V: INSObject + ?Sized> Index<&'a K> for NSDictionary<K, V> {
170176
type Output = V;
171177

172178
fn index(&self, index: &K) -> &V {

objc2-foundation/src/enumerator.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ use objc2::{msg_send, Encode, Encoding, RefEncode};
1111

1212
use super::INSObject;
1313

14-
pub struct NSEnumerator<'a, T: INSObject> {
14+
pub struct NSEnumerator<'a, T: INSObject + ?Sized> {
1515
id: Id<Object, Owned>,
1616
item: PhantomData<&'a T>,
1717
}
1818

19-
impl<'a, T: INSObject> NSEnumerator<'a, T> {
19+
impl<'a, T: INSObject + ?Sized> NSEnumerator<'a, T> {
2020
/// TODO
2121
///
2222
/// # Safety
@@ -32,7 +32,7 @@ impl<'a, T: INSObject> NSEnumerator<'a, T> {
3232
}
3333
}
3434

35-
impl<'a, T: INSObject> Iterator for NSEnumerator<'a, T> {
35+
impl<'a, T: INSObject + ?Sized> Iterator for NSEnumerator<'a, T> {
3636
type Item = &'a T;
3737

3838
fn next(&mut self) -> Option<&'a T> {
@@ -49,14 +49,14 @@ pub unsafe trait INSFastEnumeration: INSObject {
4949
}
5050

5151
#[repr(C)]
52-
struct NSFastEnumerationState<T: INSObject> {
52+
struct NSFastEnumerationState<T: INSObject + ?Sized> {
5353
state: c_ulong, // TODO: Verify this is actually always 64 bit
5454
items_ptr: *const *const T,
5555
mutations_ptr: *mut c_ulong,
5656
extra: [c_ulong; 5],
5757
}
5858

59-
unsafe impl<T: INSObject> Encode for NSFastEnumerationState<T> {
59+
unsafe impl<T: INSObject + ?Sized> Encode for NSFastEnumerationState<T> {
6060
const ENCODING: Encoding<'static> = Encoding::Struct(
6161
"?",
6262
&[
@@ -68,7 +68,7 @@ unsafe impl<T: INSObject> Encode for NSFastEnumerationState<T> {
6868
);
6969
}
7070

71-
unsafe impl<T: INSObject> RefEncode for NSFastEnumerationState<T> {
71+
unsafe impl<T: INSObject + ?Sized> RefEncode for NSFastEnumerationState<T> {
7272
const ENCODING_REF: Encoding<'static> = Encoding::Pointer(&Self::ENCODING);
7373
}
7474

objc2-foundation/src/lib.rs

Lines changed: 1 addition & 0 deletions
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-foundation/src/macros.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,15 @@
88
/// must be correct for this class.
99
macro_rules! object_struct {
1010
(unsafe $name:ident, $ownership:ty) => {
11-
// TODO: `extern type`
11+
#[cfg(not(feature = "unstable_extern_types"))]
1212
#[repr(C)]
1313
pub struct $name {
1414
_private: [u8; 0],
1515
}
16+
#[cfg(feature = "unstable_extern_types")]
17+
extern "C" {
18+
pub type $name;
19+
}
1620

1721
unsafe impl ::objc2::Message for $name {}
1822

objc2-foundation/src/object.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub unsafe trait INSObject: Message {
2424
unsafe { msg_send![self, hash] }
2525
}
2626

27-
fn is_equal<T: INSObject>(&self, other: &T) -> bool {
27+
fn is_equal<T: INSObject + ?Sized>(&self, other: &T) -> bool {
2828
let result: Bool = unsafe { msg_send![self, isEqual: other] };
2929
result.is_true()
3030
}

objc2/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ exception = ["cc"]
3131
catch_all = ["exception"]
3232
verify_message = []
3333
unstable_autoreleasesafe = []
34+
unstable_extern_types = ["objc-sys/unstable_extern_types"]
3435

3536
[dependencies]
3637
malloc_buf = "1.0"

objc2/src/cache.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ impl CachedSel {
3838
/// Allows storing a [`Class`] reference in a static and lazily loading it.
3939
#[doc(hidden)]
4040
pub struct CachedClass {
41-
ptr: AtomicPtr<Class>,
41+
ptr: AtomicPtr<c_void>,
4242
}
4343

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

objc2/src/declare.rs

Lines changed: 3 additions & 4 deletions
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::{self, Bool, Class, Imp, Object, Protocol, Sel};
@@ -45,7 +44,7 @@ use crate::{Encode, EncodeArguments, Encoding, Message};
4544
/// Types that can be used as the implementation of an Objective-C method.
4645
pub trait MethodImplementation {
4746
/// The callee type of the method.
48-
type Callee: Message;
47+
type Callee: ?Sized + Message;
4948
/// The return type of the method.
5049
type Ret: Encode;
5150
/// The argument types of the method.
@@ -59,7 +58,7 @@ macro_rules! method_decl_impl {
5958
(-$s:ident, $r:ident, $f:ty, $($t:ident),*) => (
6059
impl<$s, $r, $($t),*> MethodImplementation for $f
6160
where
62-
$s: Message,
61+
$s: Message + ?Sized,
6362
$r: Encode,
6463
$($t: Encode,)*
6564
{
@@ -123,7 +122,7 @@ pub struct ClassDecl {
123122
impl ClassDecl {
124123
fn with_superclass(name: &str, superclass: Option<&Class>) -> Option<ClassDecl> {
125124
let name = CString::new(name).unwrap();
126-
let super_ptr = superclass.map_or(ptr::null(), |c| c) as _;
125+
let super_ptr = superclass.map_or(0 as *const _, |c| c) as _;
127126
let cls = unsafe { runtime::objc_allocateClassPair(super_ptr, name.as_ptr(), 0) };
128127
if cls.is_null() {
129128
None

objc2/src/exception.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ extern "C" {
4646
pub unsafe fn throw(exception: Option<&Id<Object, Shared>>) -> ! {
4747
let exception = match exception {
4848
Some(id) => &**id as *const Object as *mut objc_object,
49-
None => ptr::null_mut(),
49+
None => ptr::from_raw_parts_mut(ptr::null_mut(), ()),
5050
};
5151
unsafe { objc_exception_throw(exception) }
5252
}
@@ -64,7 +64,7 @@ unsafe fn try_no_ret<F: FnOnce()>(closure: F) -> Result<(), Option<Id<Object, Sh
6464
let mut closure = Some(closure);
6565
let context = &mut closure as *mut _ as *mut c_void;
6666

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

7070
if success == 0 {

objc2/src/lib.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ mod tests {
381381
#[cfg(not(feature = "verify_message"))]
382382
#[test]
383383
fn test_send_message_nil() {
384-
let nil: *mut Object = ::core::ptr::null_mut();
384+
let nil: *mut Object = 0 as *mut Object;
385385
let result: usize = unsafe { msg_send![nil, hash] };
386386
assert!(result == 0);
387387

0 commit comments

Comments
 (0)