diff --git a/objc2/src/declare.rs b/objc2/src/declare.rs
index 69a16f293..3309bacb2 100644
--- a/objc2/src/declare.rs
+++ b/objc2/src/declare.rs
@@ -56,8 +56,12 @@ pub trait MethodImplementation {
macro_rules! method_decl_impl {
(-$s:ident, $r:ident, $f:ty, $($t:ident),*) => (
- impl<$s, $r $(, $t)*> MethodImplementation for $f
- where $s: Message, $r: Encode $(, $t: Encode)* {
+ impl<$s, $r, $($t),*> MethodImplementation for $f
+ where
+ $s: Message,
+ $r: Encode,
+ $($t: Encode,)*
+ {
type Callee = $s;
type Ret = $r;
type Args = ($($t,)*);
@@ -68,8 +72,8 @@ macro_rules! method_decl_impl {
}
);
($($t:ident),*) => (
- method_decl_impl!(-T, R, extern fn(&T, Sel $(, $t)*) -> R, $($t),*);
- method_decl_impl!(-T, R, extern fn(&mut T, Sel $(, $t)*) -> R, $($t),*);
+ method_decl_impl!(-T, R, extern "C" fn(&T, Sel $(, $t)*) -> R, $($t),*);
+ method_decl_impl!(-T, R, extern "C" fn(&mut T, Sel $(, $t)*) -> R, $($t),*);
);
}
diff --git a/objc2/src/rc/autorelease.rs b/objc2/src/rc/autorelease.rs
index b23bba35b..66153591d 100644
--- a/objc2/src/rc/autorelease.rs
+++ b/objc2/src/rc/autorelease.rs
@@ -58,6 +58,23 @@ impl AutoreleasePool {
Self { context }
}
+ /// This will be removed in a future version.
+ #[cfg_attr(
+ all(debug_assertions, not(feature = "unstable_autoreleasesafe")),
+ inline
+ )]
+ #[doc(hidden)]
+ pub fn __verify_is_inner(&self) {
+ #[cfg(all(debug_assertions, not(feature = "unstable_autoreleasesafe")))]
+ POOLS.with(|c| {
+ assert_eq!(
+ c.borrow().last(),
+ Some(&self.context),
+ "Tried to use lifetime from pool that was not innermost"
+ )
+ });
+ }
+
/// Returns a shared reference to the given autoreleased pointer object.
///
/// This is the preferred way to make references from autoreleased
@@ -70,20 +87,10 @@ impl AutoreleasePool {
///
/// This is equivalent to `&*ptr`, and shares the unsafety of that, except
/// the lifetime is bound to the pool instead of being unbounded.
- #[cfg_attr(
- all(debug_assertions, not(feature = "unstable_autoreleasesafe")),
- inline
- )]
+ #[inline]
#[allow(clippy::needless_lifetimes)]
pub unsafe fn ptr_as_ref<'p, T>(&'p self, ptr: *const T) -> &'p T {
- #[cfg(all(debug_assertions, not(feature = "unstable_autoreleasesafe")))]
- POOLS.with(|c| {
- assert_eq!(
- c.borrow().last(),
- Some(&self.context),
- "Tried to create shared reference with a lifetime from a pool that was not the innermost pool"
- )
- });
+ self.__verify_is_inner();
// SAFETY: Checked by the caller
&*ptr
}
@@ -100,21 +107,11 @@ impl AutoreleasePool {
///
/// This is equivalent to `&mut *ptr`, and shares the unsafety of that,
/// except the lifetime is bound to the pool instead of being unbounded.
- #[cfg_attr(
- all(debug_assertions, not(feature = "unstable_autoreleasesafe")),
- inline
- )]
+ #[inline]
#[allow(clippy::needless_lifetimes)]
#[allow(clippy::mut_from_ref)]
pub unsafe fn ptr_as_mut<'p, T>(&'p self, ptr: *mut T) -> &'p mut T {
- #[cfg(all(debug_assertions, not(feature = "unstable_autoreleasesafe")))]
- POOLS.with(|c| {
- assert_eq!(
- c.borrow().last(),
- Some(&self.context),
- "Tried to create unique reference with a lifetime from a pool that was not the innermost pool")
- }
- );
+ self.__verify_is_inner();
// SAFETY: Checked by the caller
&mut *ptr
}
diff --git a/objc2_block/src/lib.rs b/objc2_block/src/lib.rs
index 1c6ea8c97..150120d78 100644
--- a/objc2_block/src/lib.rs
+++ b/objc2_block/src/lib.rs
@@ -231,19 +231,24 @@ macro_rules! concrete_block_impl {
);
($f:ident, $($a:ident : $t:ident),*) => (
impl<$($t: Encode,)* R: Encode, X> IntoConcreteBlock<($($t,)*)> for X
- where X: Fn($($t,)*) -> R {
+ where
+ X: Fn($($t,)*) -> R,
+ {
type Ret = R;
fn into_concrete_block(self) -> ConcreteBlock<($($t,)*), R, X> {
unsafe extern fn $f<$($t,)* R, X>(
- block_ptr: *mut ConcreteBlock<($($t,)*), R, X>
- $(, $a: $t)*) -> R
- where X: Fn($($t,)*) -> R {
+ block_ptr: *mut ConcreteBlock<($($t,)*), R, X>
+ $(, $a: $t)*
+ ) -> R
+ where
+ X: Fn($($t,)*) -> R
+ {
let block = &*block_ptr;
(block.closure)($($a),*)
}
- let f: unsafe extern fn(*mut ConcreteBlock<($($t,)*), R, X> $(, $a: $t)*) -> R = $f;
+ let f: unsafe extern "C" fn(*mut ConcreteBlock<($($t,)*), R, X> $(, $a: $t)*) -> R = $f;
unsafe {
ConcreteBlock::with_invoke(mem::transmute(f), self)
}
@@ -397,10 +402,7 @@ impl ConcreteBlock {
}
}
-impl ConcreteBlock
-where
- F: 'static,
-{
+impl ConcreteBlock {
/// Copy self onto the heap as an `RcBlock`.
pub fn copy(self) -> RcBlock {
unsafe {
@@ -415,10 +417,7 @@ where
}
}
-impl Clone for ConcreteBlock
-where
- F: Clone,
-{
+impl Clone for ConcreteBlock {
fn clone(&self) -> Self {
unsafe {
ConcreteBlock::with_invoke(mem::transmute(self.base.invoke), self.closure.clone())
diff --git a/objc2_foundation/examples/basic_usage.rs b/objc2_foundation/examples/basic_usage.rs
index 6af8fb83c..68963f36e 100644
--- a/objc2_foundation/examples/basic_usage.rs
+++ b/objc2_foundation/examples/basic_usage.rs
@@ -1,6 +1,6 @@
+use objc2::rc::autoreleasepool;
use objc2_foundation::{
- INSArray, INSCopying, INSDictionary, INSObject, INSString, NSArray, NSDictionary, NSObject,
- NSString,
+ INSArray, INSCopying, INSDictionary, INSString, NSArray, NSDictionary, NSObject, NSString,
};
fn main() {
@@ -17,7 +17,7 @@ fn main() {
for obj in array.object_enumerator() {
println!("{:?}", obj);
}
- println!("{}", array.count());
+ println!("{}", array.len());
// Turn the NSArray back into a Vec
let mut objs = NSArray::into_vec(array);
@@ -25,14 +25,17 @@ fn main() {
// Create an NSString from a str slice
let string = NSString::from_str("Hello, world!");
- println!("{}", string.as_str());
- let string2 = string.copy();
- println!("{}", string2.as_str());
+ // Use an autoreleasepool to get the `str` contents of the NSString
+ autoreleasepool(|pool| {
+ println!("{}", string.as_str(pool));
+ let string2 = string.copy();
+ println!("{}", string2.as_str(pool));
+ });
// Create a dictionary mapping strings to objects
let keys = &[&*string];
let vals = vec![obj];
let dict = NSDictionary::from_keys_and_objects(keys, vals);
- println!("{:?}", dict.object_for(&string));
- println!("{}", dict.count());
+ println!("{:?}", dict.get(&string));
+ println!("{}", dict.len());
}
diff --git a/objc2_foundation/examples/class_with_lifetime.rs b/objc2_foundation/examples/class_with_lifetime.rs
new file mode 100644
index 000000000..63230f156
--- /dev/null
+++ b/objc2_foundation/examples/class_with_lifetime.rs
@@ -0,0 +1,104 @@
+use std::marker::PhantomData;
+use std::ptr::NonNull;
+use std::sync::Once;
+
+use objc2::declare::ClassDecl;
+use objc2::rc::{Id, Owned, Shared};
+use objc2::runtime::{Class, Object, Sel};
+use objc2::{msg_send, sel};
+use objc2::{Encoding, Message, RefEncode};
+use objc2_foundation::{INSObject, NSObject};
+
+#[repr(C)]
+pub struct MyObject<'a> {
+ _priv: [u8; 0],
+ // `init` defaults ivars to all zeroes, so allow for that here
+ // TODO: Verify this claim!
+ p: PhantomData