Skip to content

Commit

Permalink
Merge pull request #547 from madsmtm/deprecate-malloc-buf
Browse files Browse the repository at this point in the history
Work towards removing `malloc_buf`
  • Loading branch information
madsmtm authored Dec 27, 2023
2 parents 937aa1a + ba3b5be commit ff4a4c1
Show file tree
Hide file tree
Showing 24 changed files with 384 additions and 170 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ env:
#
# Note: The `exception` feature is not enabled here, since it requires
# compiling C code, even if just running a `check`/`clippy` build.
INTERESTING_FEATURES: malloc,block,verify,unstable-private
INTERESTING_FEATURES: malloc,block,unstable-private
UNSTABLE_FEATURES: unstable-autoreleasesafe,unstable-c-unwind
LATEST_MACOS_FEATURE: unstable-frameworks-macos-14
# Required when we want to use a different runtime than the default `apple`
Expand Down
3 changes: 3 additions & 0 deletions crates/objc-sys/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased - YYYY-MM-DD

### Added
* Added `free` method (same as `libc::free`).


## 0.3.2 - 2023-12-03

Expand Down
5 changes: 5 additions & 0 deletions crates/objc-sys/src/class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ extern_c! {
pub fn objc_lookUpClass(name: *const c_char) -> *const objc_class;
#[cfg(any(doc, not(objfw)))]
pub fn objc_getMetaClass(name: *const c_char) -> *const objc_class;
/// The returned array is deallocated with [`free`][crate::free].
pub fn objc_copyClassList(out_len: *mut c_uint) -> *mut *const objc_class;
pub fn objc_getClassList(buffer: *mut *const objc_class, buffer_len: c_int) -> c_int;

Expand Down Expand Up @@ -98,21 +99,25 @@ extern_c! {
-> BOOL;

#[cfg(any(doc, not(objfw)))] // Available in newer versions
/// The return value is deallocated with [`free`][crate::free].
pub fn class_copyIvarList(
cls: *const objc_class,
out_len: *mut c_uint,
) -> *mut *const objc_ivar;
#[cfg(any(doc, not(objfw)))] // Available in newer versions
/// The returned array is deallocated with [`free`][crate::free].
pub fn class_copyMethodList(
cls: *const objc_class,
out_len: *mut c_uint,
) -> *mut *const objc_method;
#[cfg(any(doc, not(objfw)))] // Available in newer versions
/// The returned array is deallocated with [`free`][crate::free].
pub fn class_copyPropertyList(
cls: *const objc_class,
out_len: *mut c_uint,
) -> *mut *const objc_property;
#[cfg(any(doc, not(objfw)))]
/// The returned array is deallocated with [`free`][crate::free].
pub fn class_copyProtocolList(
cls: *const objc_class,
out_len: *mut c_uint,
Expand Down
29 changes: 15 additions & 14 deletions crates/objc-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,9 +142,9 @@ macro_rules! extern_c_unwind {

mod class;
mod constants;

mod exception;
mod image_info;
mod libc;
mod message;
mod method;
mod object;
Expand All @@ -155,19 +155,20 @@ mod selector;
mod types;
mod various;

pub use class::*;
pub use constants::*;
pub use exception::*;
pub use image_info::*;
pub use message::*;
pub use method::*;
pub use object::*;
pub use property::*;
pub use protocol::*;
pub use rc::*;
pub use selector::*;
pub use types::*;
pub use various::*;
pub use self::class::*;
pub use self::constants::*;
pub use self::exception::*;
pub use self::image_info::*;
pub use self::libc::*;
pub use self::message::*;
pub use self::method::*;
pub use self::object::*;
pub use self::property::*;
pub use self::protocol::*;
pub use self::rc::*;
pub use self::selector::*;
pub use self::types::*;
pub use self::various::*;

/// We don't know much about the actual structs, so better mark them `!Send`,
/// `!Sync`, `!UnwindSafe`, `!RefUnwindSafe`, `!Unpin` and as mutable behind
Expand Down
19 changes: 19 additions & 0 deletions crates/objc-sys/src/libc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
use core::ffi::c_void;

// SAFETY: The signatures in here are the exact same as in `libc`.
extern_c! {
/// The Objective-C runtime has several methods, usually with "`copy`" in
/// their name, whose return value is allocated with C's `malloc` and
/// deallocated with C's `free` method.
///
/// As such, `free` is actually also part of the Objective-C runtime.
///
/// We expose this instead of using [`libc::free`], to avoid having `libc`
/// as a dependency.
///
/// [`libc::free`]: https://docs.rs/libc/latest/libc/fn.free.html
//
// Note: This is linked automatically by either `std` or transitively by
// `libobjc`.
pub fn free(p: *mut c_void);
}
2 changes: 2 additions & 0 deletions crates/objc-sys/src/method.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ pub struct objc_method_description {

extern_c! {
#[cfg(any(doc, not(objfw)))]
/// The return value is deallocated with [`free`][crate::free].
pub fn method_copyArgumentType(method: *const objc_method, index: c_uint) -> *mut c_char;
#[cfg(any(doc, not(objfw)))]
/// The return value is deallocated with [`free`][crate::free].
pub fn method_copyReturnType(method: *const objc_method) -> *mut c_char;
#[cfg(any(doc, not(objfw)))]
pub fn method_exchangeImplementations(method1: *mut objc_method, method2: *mut objc_method);
Expand Down
1 change: 1 addition & 0 deletions crates/objc-sys/src/property.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct objc_property_attribute_t {

extern_c! {
#[cfg(any(doc, not(objfw)))]
/// The returned array is deallocated with [`free`][crate::free].
pub fn property_copyAttributeList(
property: *const objc_property,
out_len: *mut c_uint,
Expand Down
4 changes: 4 additions & 0 deletions crates/objc-sys/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ extern_c! {
#[cfg(any(doc, not(objfw)))]
pub fn objc_getProtocol(name: *const c_char) -> *const objc_protocol;
#[cfg(any(doc, not(objfw)))]
/// The returned array is deallocated with [`free`][crate::free].
pub fn objc_copyProtocolList(out_len: *mut c_uint) -> *mut *const objc_protocol;

#[cfg(any(doc, not(objfw)))]
Expand Down Expand Up @@ -57,18 +58,21 @@ extern_c! {
#[cfg(any(doc, not(objfw)))]
pub fn protocol_addProtocol(proto: *mut objc_protocol, addition: *const objc_protocol);
#[cfg(any(doc, not(objfw)))]
/// The returned array is deallocated with [`free`][crate::free].
pub fn protocol_copyMethodDescriptionList(
proto: *const objc_protocol,
is_required_method: BOOL,
is_instance_method: BOOL,
out_len: *mut c_uint,
) -> *mut objc_method_description;
#[cfg(any(doc, not(objfw)))]
/// The returned array is deallocated with [`free`][crate::free].
pub fn protocol_copyPropertyList(
proto: *const objc_protocol,
out_len: *mut c_uint,
) -> *mut *const objc_property;
#[cfg(any(doc, not(objfw)))]
/// The returned array is deallocated with [`free`][crate::free].
pub fn protocol_copyProtocolList(
proto: *const objc_protocol,
out_len: *mut c_uint,
Expand Down
1 change: 1 addition & 0 deletions crates/objc-sys/src/various.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ extern_c! {
out_len: *mut c_uint,
) -> *mut *const c_char;
#[cfg(any(doc, apple))]
/// The returned array is deallocated with [`free`][crate::free].
pub fn objc_copyImageNames(out_len: *mut c_uint) -> *mut *const c_char;

#[cfg(any(doc, apple, objfw))]
Expand Down
14 changes: 14 additions & 0 deletions crates/objc2/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased - YYYY-MM-DD

### Added
* Made the following runtime methods available without the `"malloc"` feature
flag:
- `Method::return_type`.
- `Method::argument_type`.
- `AnyClass::classes`.
- `AnyClass::instance_methods`.
- `AnyClass::adopted_protocols`.
- `AnyClass::instance_variables`.
- `AnyProtocol::protocols`.
- `AnyProtocol::adopted_protocols`.

### Changed
* Moved `ClassBuilder` and `ProtocolBuilder` from the `declare` module to the
`runtime` module. The old locations are deprecated.
* Enabled the `"verify"` feature flag's functionality when debug assertions are
enabled.


## 0.5.0 - 2023-12-03
Expand Down
15 changes: 7 additions & 8 deletions crates/objc2/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,6 @@ exception = ["objc-sys/unstable-exception"]
# Wrap every `objc2::msg_send` call in a `@try/@catch` block
catch-all = ["exception"]

# Enable all verification steps when debug assertions are enabled.
verify = ["malloc"]

# Allow `*const c_void` and `*mut c_void` to be used as arguments and return
# types where other pointers were expected.
#
Expand All @@ -45,12 +42,14 @@ relax-void-encoding = []
# Enable deprecation of using `msg_send!` without a comma between arguments.
unstable-msg-send-always-comma = []

# Expose features that require linking to `libc::free`.
#
# This is not enabled by default because most users won't need it, and it
# increases compilation time.
# This was necessary to access certain functionality in the past, but it is no
# longer required.
malloc = ["malloc_buf"]

# This was necessary to enable certain debug assertions in the past, but it is
# no longer required.
verify = []

# Make the `sel!` macro look up the selector statically.
#
# The plan is to enable this by default, but right now we are uncertain of
Expand Down Expand Up @@ -116,7 +115,7 @@ harness = false

[package.metadata.docs.rs]
default-target = "x86_64-apple-darwin"
features = ["exception", "malloc", "unstable-docsrs"]
features = ["exception", "unstable-docsrs"]

targets = [
# MacOS
Expand Down
9 changes: 3 additions & 6 deletions crates/objc2/examples/introspection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,9 @@ fn main() {
"-[NSObject hash] takes {} parameters",
method.arguments_count()
);
#[cfg(feature = "malloc")]
{
let hash_return = method.return_type();
println!("-[NSObject hash] return type: {hash_return:?}");
assert!(usize::ENCODING.equivalent_to_str(&hash_return));
}
let hash_return = method.return_type();
println!("-[NSObject hash] return type: {hash_return:?}");
assert!(usize::ENCODING.equivalent_to_str(&hash_return));

// Create an instance
let obj = NSObject::new();
Expand Down
36 changes: 18 additions & 18 deletions crates/objc2/src/__macro_helpers/declare_class.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
use alloc::vec::Vec;
use core::marker::PhantomData;
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
use std::collections::HashSet;

use crate::encode::{Encode, Encoding};
use crate::rc::{Allocated, Id};
use crate::runtime::{
AnyClass, AnyObject, ClassBuilder, MessageReceiver, MethodImplementation, Sel,
};
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
use crate::runtime::{AnyProtocol, MethodDescription};
use crate::{ClassType, DeclaredClass, Message, ProtocolType};

Expand Down Expand Up @@ -243,7 +243,7 @@ impl<T: DeclaredClass> ClassBuilderHelper<T> {
self.builder.add_protocol(protocol);
}

#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
{
ClassProtocolMethodsBuilder {
builder: self,
Expand All @@ -265,7 +265,7 @@ impl<T: DeclaredClass> ClassBuilderHelper<T> {
}
}

#[cfg(not(all(debug_assertions, feature = "verify")))]
#[cfg(not(debug_assertions))]
{
ClassProtocolMethodsBuilder { builder: self }
}
Expand Down Expand Up @@ -303,19 +303,19 @@ impl<T: DeclaredClass> ClassBuilderHelper<T> {
#[derive(Debug)]
pub struct ClassProtocolMethodsBuilder<'a, T: ?Sized> {
builder: &'a mut ClassBuilderHelper<T>,
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
protocol: Option<&'static AnyProtocol>,
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
required_instance_methods: Vec<MethodDescription>,
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
optional_instance_methods: Vec<MethodDescription>,
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
registered_instance_methods: HashSet<Sel>,
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
required_class_methods: Vec<MethodDescription>,
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
optional_class_methods: Vec<MethodDescription>,
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
registered_class_methods: HashSet<Sel>,
}

Expand All @@ -326,7 +326,7 @@ impl<T: DeclaredClass> ClassProtocolMethodsBuilder<'_, T> {
where
F: MethodImplementation<Callee = T>,
{
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
if let Some(protocol) = self.protocol {
let _types = self
.required_instance_methods
Expand All @@ -344,7 +344,7 @@ impl<T: DeclaredClass> ClassProtocolMethodsBuilder<'_, T> {
// SAFETY: Checked by caller
unsafe { self.builder.add_method(sel, func) };

#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
if !self.registered_instance_methods.insert(sel) {
unreachable!("already added")
}
Expand All @@ -355,7 +355,7 @@ impl<T: DeclaredClass> ClassProtocolMethodsBuilder<'_, T> {
where
F: MethodImplementation<Callee = AnyClass>,
{
#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
if let Some(protocol) = self.protocol {
let _types = self
.required_class_methods
Expand All @@ -373,13 +373,13 @@ impl<T: DeclaredClass> ClassProtocolMethodsBuilder<'_, T> {
// SAFETY: Checked by caller
unsafe { self.builder.add_class_method(sel, func) };

#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
if !self.registered_class_methods.insert(sel) {
unreachable!("already added")
}
}

#[cfg(all(debug_assertions, feature = "verify"))]
#[cfg(debug_assertions)]
pub fn finish(self) {
let superclass = self.builder.builder.superclass();

Expand Down Expand Up @@ -427,6 +427,6 @@ impl<T: DeclaredClass> ClassProtocolMethodsBuilder<'_, T> {
}

#[inline]
#[cfg(not(all(debug_assertions, feature = "verify")))]
#[cfg(not(debug_assertions))]
pub fn finish(self) {}
}
3 changes: 1 addition & 2 deletions crates/objc2/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,7 @@
//! # panic!("does not panic in release mode, so for testing we make it!");
//! ```
//!
//! This library contains further such debug checks, most of which are enabled
//! by default. To enable all of them, use the `"verify"` cargo feature.
//! This library contains further such debug checks.
//!
//! [`Vec`]: std::vec::Vec
//!
Expand Down
Loading

0 comments on commit ff4a4c1

Please sign in to comment.