Skip to content

Commit

Permalink
Add unstable_extern_types feature
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
madsmtm committed Nov 2, 2021
1 parent dc303e6 commit 2a23ed9
Show file tree
Hide file tree
Showing 17 changed files with 76 additions and 44 deletions.
3 changes: 3 additions & 0 deletions objc-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ readme = "README.md"
# See https://doc.rust-lang.org/cargo/reference/build-scripts.html#overriding-build-scripts
links = "objc"
build = "build.rs"

[features]
unstable_extern_types = []
13 changes: 11 additions & 2 deletions objc-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//! [objc4-mirror]: https://github.com/madsmtm/objc4-mirror.git

#![no_std]
#![cfg_attr(feature = "unstable_extern_types", feature(extern_types))]
#![allow(clippy::upper_case_acronyms)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
Expand All @@ -26,8 +27,11 @@
// See https://github.com/japaric/cty/issues/14.
extern crate std;

use core::cell::UnsafeCell;
use core::marker::{PhantomData, PhantomPinned};
#[cfg(not(feature = "unstable_extern_types"))]
use core::{
cell::UnsafeCell,
marker::{PhantomData, PhantomPinned},
};

mod class;
mod constants;
Expand Down Expand Up @@ -61,4 +65,9 @@ pub use various::*;
/// also less of a breaking change on our part if we re-add these later).
///
/// TODO: Replace this with `extern type` to also mark it as unsized.
#[cfg(not(feature = "unstable_extern_types"))]
type OpaqueData = PhantomData<(UnsafeCell<*const ()>, PhantomPinned)>;
#[cfg(feature = "unstable_extern_types")]
extern "C" {
type OpaqueData;
}
2 changes: 2 additions & 0 deletions objc2-foundation/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ default = ["block"]
# Provided as a way to cut down on dependencies
block = ["block2"]

unstable_extern_types = ["objc2/unstable_extern_types", "objc-sys/unstable_extern_types"]

[dependencies]
block2 = { path = "../block2", optional = true }
objc2 = { path = "../objc2" }
Expand Down
16 changes: 10 additions & 6 deletions objc2-foundation/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ unsafe fn from_refs<A: INSArray + ?Sized>(refs: &[&A::Item]) -> Id<A, A::Ownersh
}

pub unsafe trait INSArray: INSObject {
type Item: INSObject;
type Item: INSObject + ?Sized;
type ItemOwnership: Ownership;

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

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

unsafe impl<T: INSObject, O: Ownership> INSObject for NSArray<T, O> {
unsafe impl<T: ?Sized, O: Ownership> objc2::RefEncode for NSArray<T, O> {
const ENCODING_REF: objc2::Encoding<'static> = objc2::Encoding::Object;
}

unsafe impl<T: INSObject + ?Sized, O: Ownership> INSObject for NSArray<T, O> {
/// The `NSArray` itself (length and number of items) is always immutable,
/// but we would like to know when we're the only owner of the array, to
/// allow mutation of the array's items.
Expand All @@ -184,14 +188,14 @@ unsafe impl<T: INSObject, O: Ownership> INSObject for NSArray<T, O> {
}
}

unsafe impl<T: INSObject, O: Ownership> INSArray for NSArray<T, O> {
unsafe impl<T: INSObject + ?Sized, O: Ownership> INSArray for NSArray<T, O> {
type Item = T;
type ItemOwnership = O;
}

// Copying only possible when ItemOwnership = Shared

unsafe impl<T: INSObject> INSCopying for NSArray<T, Shared> {
unsafe impl<T: INSObject + ?Sized> INSCopying for NSArray<T, Shared> {
type Output = NSArray<T, Shared>;
}

Expand Down
4 changes: 2 additions & 2 deletions objc2-foundation/src/copying.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub unsafe trait INSCopying: INSObject {
/// // would be able to create aliasing mutable references!
/// let y: Id<MyObject, Owned> = x.copy();
/// ```
type Output: INSObject;
type Output: INSObject + ?Sized;

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

fn mutable_copy(&self) -> Id<Self::Output, Owned> {
unsafe {
Expand Down
22 changes: 14 additions & 8 deletions objc2-foundation/src/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ where
}

pub unsafe trait INSDictionary: INSObject {
type Key: INSObject;
type Value: INSObject;
type Key: INSObject + ?Sized;
type Value: INSObject + ?Sized;
type ValueOwnership: Ownership;

unsafe_def_fn!(fn new);
Expand Down Expand Up @@ -141,32 +141,38 @@ pub unsafe trait INSDictionary: INSObject {
}
}

pub struct NSDictionary<K, V> {
pub struct NSDictionary<K: ?Sized, V: ?Sized> {
key: PhantomData<Id<K, Shared>>,
obj: PhantomData<Id<V, Owned>>,
}

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

unsafe impl<K: INSObject, V: INSObject> INSObject for NSDictionary<K, V> {
unsafe impl<K: ?Sized, V: ?Sized> ::objc2::RefEncode for NSDictionary<K, V> {
const ENCODING_REF: objc2::Encoding<'static> = objc2::Encoding::Object;
}

unsafe impl<K: INSObject + ?Sized, V: INSObject + ?Sized> INSObject for NSDictionary<K, V> {
type Ownership = Shared;

fn class() -> &'static Class {
class!(NSDictionary)
}
}

unsafe impl<K: INSObject, V: INSObject> INSDictionary for NSDictionary<K, V> {
unsafe impl<K: INSObject + ?Sized, V: INSObject + ?Sized> INSDictionary for NSDictionary<K, V> {
type Key = K;
type Value = V;
type ValueOwnership = Owned;
}

unsafe impl<K: INSObject, V: INSObject> INSFastEnumeration for NSDictionary<K, V> {
unsafe impl<K: INSObject + ?Sized, V: INSObject + ?Sized> INSFastEnumeration
for NSDictionary<K, V>
{
type Item = K;
}

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

fn index(&self, index: &K) -> &V {
Expand Down
12 changes: 6 additions & 6 deletions objc2-foundation/src/enumerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ use objc2::{msg_send, Encode, Encoding, RefEncode};

use super::INSObject;

pub struct NSEnumerator<'a, T: INSObject> {
pub struct NSEnumerator<'a, T: INSObject + ?Sized> {
id: Id<Object, Owned>,
item: PhantomData<&'a T>,
}

impl<'a, T: INSObject> NSEnumerator<'a, T> {
impl<'a, T: INSObject + ?Sized> NSEnumerator<'a, T> {
/// TODO
///
/// # Safety
Expand All @@ -32,7 +32,7 @@ impl<'a, T: INSObject> NSEnumerator<'a, T> {
}
}

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

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

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

unsafe impl<T: INSObject> Encode for NSFastEnumerationState<T> {
unsafe impl<T: INSObject + ?Sized> Encode for NSFastEnumerationState<T> {
const ENCODING: Encoding<'static> = Encoding::Struct(
"?",
&[
Expand All @@ -68,7 +68,7 @@ unsafe impl<T: INSObject> Encode for NSFastEnumerationState<T> {
);
}

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

Expand Down
1 change: 1 addition & 0 deletions objc2-foundation/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#![no_std]
#![cfg_attr(feature = "unstable_extern_types", feature(extern_types))]
#![warn(elided_lifetimes_in_paths)]
#![deny(non_ascii_idents)]
#![warn(unreachable_pub)]
Expand Down
6 changes: 5 additions & 1 deletion objc2-foundation/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,15 @@
/// must be correct for this class.
macro_rules! object_struct {
(unsafe $name:ident, $ownership:ty) => {
// TODO: `extern type`
#[cfg(not(feature = "unstable_extern_types"))]
#[repr(C)]
pub struct $name {
_private: [u8; 0],
}
#[cfg(feature = "unstable_extern_types")]
extern "C" {
pub type $name;
}

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

Expand Down
2 changes: 1 addition & 1 deletion objc2-foundation/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub unsafe trait INSObject: Message {
unsafe { msg_send![self, hash] }
}

fn is_equal<T: INSObject>(&self, other: &T) -> bool {
fn is_equal<T: INSObject + ?Sized>(&self, other: &T) -> bool {
let result: Bool = unsafe { msg_send![self, isEqual: other] };
result.is_true()
}
Expand Down
1 change: 1 addition & 0 deletions objc2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ exception = ["cc"]
catch_all = ["exception"]
verify_message = []
unstable_autoreleasesafe = []
unstable_extern_types = ["objc-sys/unstable_extern_types"]

[dependencies]
malloc_buf = "1.0"
Expand Down
4 changes: 2 additions & 2 deletions objc2/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl CachedSel {
/// Allows storing a [`Class`] reference in a static and lazily loading it.
#[doc(hidden)]
pub struct CachedClass {
ptr: AtomicPtr<Class>,
ptr: AtomicPtr<c_void>,
}

impl CachedClass {
Expand All @@ -55,7 +55,7 @@ impl CachedClass {
#[doc(hidden)]
pub unsafe fn get(&self, name: &str) -> Option<&'static Class> {
// `Relaxed` should be fine since `objc_getClass` is thread-safe.
let ptr = self.ptr.load(Ordering::Relaxed);
let ptr = self.ptr.load(Ordering::Relaxed) as *const Class;
if ptr.is_null() {
let cls = unsafe { runtime::objc_getClass(name.as_ptr() as *const _) } as *const Class;
self.ptr.store(cls as *mut _, Ordering::Relaxed);
Expand Down
7 changes: 3 additions & 4 deletions objc2/src/declare.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ use alloc::format;
use alloc::string::ToString;
use core::mem;
use core::mem::ManuallyDrop;
use core::ptr;
use std::ffi::CString;

use crate::runtime::{self, Bool, Class, Imp, Object, Protocol, Sel};
Expand All @@ -45,7 +44,7 @@ use crate::{Encode, EncodeArguments, Encoding, Message};
/// Types that can be used as the implementation of an Objective-C method.
pub trait MethodImplementation {
/// The callee type of the method.
type Callee: Message;
type Callee: ?Sized + Message;
/// The return type of the method.
type Ret: Encode;
/// The argument types of the method.
Expand All @@ -59,7 +58,7 @@ macro_rules! method_decl_impl {
(-$s:ident, $r:ident, $f:ty, $($t:ident),*) => (
impl<$s, $r, $($t),*> MethodImplementation for $f
where
$s: Message,
$s: Message + ?Sized,
$r: Encode,
$($t: Encode,)*
{
Expand Down Expand Up @@ -123,7 +122,7 @@ pub struct ClassDecl {
impl ClassDecl {
fn with_superclass(name: &str, superclass: Option<&Class>) -> Option<ClassDecl> {
let name = CString::new(name).unwrap();
let super_ptr = superclass.map_or(ptr::null(), |c| c) as _;
let super_ptr = superclass.map_or(0 as *const _, |c| c) as _;
let cls = unsafe { runtime::objc_allocateClassPair(super_ptr, name.as_ptr(), 0) };
if cls.is_null() {
None
Expand Down
4 changes: 2 additions & 2 deletions objc2/src/exception.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ extern "C" {
pub unsafe fn throw(exception: Option<&Id<Object, Shared>>) -> ! {
let exception = match exception {
Some(id) => &**id as *const Object as *mut objc_object,
None => ptr::null_mut(),
None => ptr::from_raw_parts_mut(ptr::null_mut(), ()),
};
unsafe { objc_exception_throw(exception) }
}
Expand All @@ -64,7 +64,7 @@ unsafe fn try_no_ret<F: FnOnce()>(closure: F) -> Result<(), Option<Id<Object, Sh
let mut closure = Some(closure);
let context = &mut closure as *mut _ as *mut c_void;

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

if success == 0 {
Expand Down
1 change: 1 addition & 0 deletions objc2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ The bindings can be used on Linux or *BSD utilizing the
feature = "unstable_autoreleasesafe",
feature(negative_impls, auto_traits)
)]
#![cfg_attr(feature = "unstable_extern_types", feature(ptr_metadata))]
#![warn(elided_lifetimes_in_paths)]
#![warn(missing_docs)]
#![deny(non_ascii_idents)]
Expand Down
2 changes: 1 addition & 1 deletion objc2/src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ mod tests {
#[cfg(not(feature = "verify_message"))]
#[test]
fn test_send_message_nil() {
let nil: *mut Object = ::core::ptr::null_mut();
let nil: *mut Object = 0 as *mut Object;
let result: usize = unsafe { msg_send![nil, hash] };
assert!(result == 0);

Expand Down
Loading

0 comments on commit 2a23ed9

Please sign in to comment.