Skip to content

Commit

Permalink
Remove NSCopying/NSMutableCopying workarounds in header translator
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Sep 11, 2023
1 parent d4cd63b commit 6be088f
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 39 deletions.
5 changes: 0 additions & 5 deletions crates/header-translator/src/rust_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,12 +186,10 @@ enum IdType {
}

impl IdType {
#[allow(dead_code)]
fn _id(&self) -> Option<&ItemIdentifier> {
match self {
Self::Class { id, .. } => Some(id),
Self::AnyObject { protocols } => match &**protocols {
[id] if id.name == "NSCopying" || id.name == "NSMutableCopying" => None,
[id] => Some(id),
_ => None,
},
Expand Down Expand Up @@ -370,9 +368,6 @@ impl fmt::Display for IdType {
Self::AnyObject { protocols } => match &**protocols {
[] => write!(f, "AnyObject"),
[id] if id.is_nsobject() => write!(f, "NSObject"),
[id] if id.name == "NSCopying" || id.name == "NSMutableCopying" => {
write!(f, "AnyObject")
}
[id] => write!(f, "ProtocolObject<dyn {}>", id.path()),
// TODO: Handle this better
_ => write!(f, "TodoProtocols"),
Expand Down
8 changes: 1 addition & 7 deletions crates/header-translator/src/stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1680,13 +1680,7 @@ impl fmt::Display for Stmt {

write!(f, " pub unsafe trait {}", id.name)?;
if !protocols.is_empty() {
for (i, protocol) in protocols
.iter()
.filter(|protocol| {
protocol.name != "NSCopying" && protocol.name != "NSMutableCopying"
})
.enumerate()
{
for (i, protocol) in protocols.iter().enumerate() {
if i == 0 {
write!(f, ": ")?;
} else {
Expand Down
3 changes: 3 additions & 0 deletions crates/icrate/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
`NSTextAttachmentCellProtocol` and `NSFileProviderItemProtocol`.
* **BREAKING**: Generic types no longer strictly require `Message` (although
most of their trait implementations still require that).
* **BREAKING**: Removed a workaround that made the `NSCopying` and
`NSMutableCopying` protocols not act as regular protocols (many methods used
`AnyObject` instead of the correct `ProtocolObject<dyn NSCopying>`).


## icrate 0.0.4 - 2023-07-31
Expand Down
48 changes: 22 additions & 26 deletions crates/icrate/src/additions/Foundation/dictionary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,17 @@ use crate::common::*;
use crate::Foundation::NSMutableDictionary;
use crate::Foundation::{self, NSCopying, NSDictionary};

fn keys_to_ptr<Q>(keys: &[&Q]) -> *mut NonNull<ProtocolObject<dyn NSCopying>>
where
Q: Message + NSCopying,
{
let keys: *mut NonNull<Q> = util::ref_ptr_cast_const(keys.as_ptr());
// SAFETY: `Q` is `Message + NSCopying`, and is therefore safe to cast to
// `ProtocolObject<dyn NSCopying>`.
let keys: *mut NonNull<ProtocolObject<dyn NSCopying>> = keys.cast();
keys
}

impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSDictionary<K, V> {
pub fn from_vec<Q>(keys: &[&Q], mut objects: Vec<Id<V>>) -> Id<Self>
where
Expand All @@ -31,8 +42,7 @@ impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSDictionary<K, V> {
// different lengths, either would be fine.
let count = min(keys.len(), objects.len());

let keys: *mut NonNull<Q> = util::ref_ptr_cast_const(keys.as_ptr());
let keys: *mut NonNull<AnyObject> = keys.cast();
let keys = keys_to_ptr(keys);
let objects = util::id_ptr_cast(objects.as_mut_ptr());

// SAFETY:
Expand Down Expand Up @@ -62,8 +72,7 @@ impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSDictionary<K, V> {
{
let count = min(keys.len(), objects.len());

let keys: *mut NonNull<Q> = util::ref_ptr_cast_const(keys.as_ptr());
let keys: *mut NonNull<AnyObject> = keys.cast();
let keys = keys_to_ptr(keys);
let objects = util::id_ptr_cast_const(objects.as_ptr());

// SAFETY: See `NSDictionary::from_vec` and `NSArray::from_id_slice`.
Expand All @@ -77,8 +86,7 @@ impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSDictionary<K, V> {
{
let count = min(keys.len(), objects.len());

let keys: *mut NonNull<Q> = util::ref_ptr_cast_const(keys.as_ptr());
let keys: *mut NonNull<AnyObject> = keys.cast();
let keys = keys_to_ptr(keys);
let objects = util::ref_ptr_cast_const(objects.as_ptr());

// SAFETY: See `NSDictionary::from_vec` and `NSArray::from_slice`.
Expand All @@ -95,7 +103,7 @@ impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSMutableDictionary<K,
let count = min(keys.len(), objects.len());

let keys: *mut NonNull<Q> = util::ref_ptr_cast_const(keys.as_ptr());
let keys: *mut NonNull<AnyObject> = keys.cast();
let keys: *mut NonNull<ProtocolObject<dyn NSCopying>> = keys.cast();
let objects = util::id_ptr_cast(objects.as_mut_ptr());

// SAFETY: See `NSDictionary::from_vec`
Expand All @@ -109,8 +117,7 @@ impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSMutableDictionary<K,
{
let count = min(keys.len(), objects.len());

let keys: *mut NonNull<Q> = util::ref_ptr_cast_const(keys.as_ptr());
let keys: *mut NonNull<AnyObject> = keys.cast();
let keys = keys_to_ptr(keys);
let objects = util::id_ptr_cast_const(objects.as_ptr());

// SAFETY: See `NSDictionary::from_vec` and `NSArray::from_id_slice`.
Expand All @@ -124,8 +131,7 @@ impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSMutableDictionary<K,
{
let count = min(keys.len(), objects.len());

let keys: *mut NonNull<Q> = util::ref_ptr_cast_const(keys.as_ptr());
let keys: *mut NonNull<AnyObject> = keys.cast();
let keys = keys_to_ptr(keys);
let objects = util::ref_ptr_cast_const(objects.as_ptr());

// SAFETY: See `NSDictionary::from_vec` and `NSArray::from_slice`.
Expand Down Expand Up @@ -335,13 +341,8 @@ impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSMutableDictionary<K,
.get(key)
.map(|old_obj| unsafe { util::mutable_collection_retain_removed_id(old_obj) });

// SAFETY: It is always safe to transmute an `&T` where `T: Message`
// to `&AnyObject`.
let key: NonNull<K> = NonNull::from(key);
let key: NonNull<AnyObject> = key.cast();
let key: &AnyObject = unsafe { key.as_ref() };
// SAFETY: The key is NSCopying (see `NSDictionary::from_vec`), and we
// have ownership over the value.
let key = ProtocolObject::from_ref(key);
// SAFETY: We have ownership over the value.
unsafe { self.setObject_forKey(&value, key) };
old_obj
}
Expand Down Expand Up @@ -371,14 +372,9 @@ impl<K: Message + Eq + Hash + HasStableHash, V: Message> NSMutableDictionary<K,
.get(key)
.map(|old_obj| unsafe { util::mutable_collection_retain_removed_id(old_obj) });

// SAFETY: It is always safe to transmute an `&T` where `T: Message`
// to `&AnyObject`.
let key: NonNull<K> = NonNull::from(key);
let key: NonNull<AnyObject> = key.cast();
let key: &AnyObject = unsafe { key.as_ref() };
// SAFETY: The key is NSCopying (see `NSDictionary::from_vec`), and
// the value is `IsRetainable` (and hence safe for the collection to
// retain).
let key = ProtocolObject::from_ref(key);
// SAFETY: The value is `IsRetainable`, and hence safe for the
// collection to retain.
unsafe { self.setObject_forKey(value, key) };
old_obj
}
Expand Down
2 changes: 1 addition & 1 deletion crates/icrate/src/generated

0 comments on commit 6be088f

Please sign in to comment.