Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Work towards removing malloc_buf #547

Merged
merged 3 commits into from
Dec 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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