Skip to content

Commit 5d3790b

Browse files
committed
Implement Borrow and BorrowMut in object! macro
1 parent 481d817 commit 5d3790b

File tree

4 files changed

+74
-27
lines changed

4 files changed

+74
-27
lines changed

objc2-foundation/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2828
* Added `NSPoint`.
2929
* Added `NSSize`.
3030
* Added `NSRect`.
31+
* Implement `Borrow` and `BorrowMut` for all objects.
3132

3233
### Changed
3334
* **BREAKING**: Removed the following helper traits in favor of inherent

objc2-foundation/src/data.rs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,9 @@ impl AsRef<[u8]> for NSData {
9898
}
9999
}
100100

101+
// Note: We don't implement `Borrow<[u8]>` since we can't guarantee that `Eq`,
102+
// `Ord` and `Hash` are equal for `NSData` vs. `[u8]`!
103+
101104
impl<I: SliceIndex<[u8]>> Index<I> for NSData {
102105
type Output = I::Output;
103106

@@ -433,29 +436,34 @@ mod tests {
433436
}
434437

435438
#[test]
436-
fn test_as_ref() {
437-
fn impls_as_ref<T: AsRef<U> + ?Sized, U: ?Sized>(_: &T) {}
438-
fn impls_as_mut<T: AsMut<U> + ?Sized, U: ?Sized>(_: &mut T) {}
439+
fn test_as_ref_borrow() {
440+
use core::borrow::{Borrow, BorrowMut};
441+
442+
fn impls_borrow<T: AsRef<U> + Borrow<U> + ?Sized, U: ?Sized>(_: &T) {}
443+
fn impls_borrow_mut<T: AsMut<U> + BorrowMut<U> + ?Sized, U: ?Sized>(_: &mut T) {}
439444

440445
let mut obj = NSMutableData::new();
441-
impls_as_ref::<Id<NSMutableData, Owned>, NSMutableData>(&obj);
442-
impls_as_mut::<Id<NSMutableData, Owned>, NSMutableData>(&mut obj);
443-
444-
impls_as_ref::<NSMutableData, NSMutableData>(&obj);
445-
impls_as_mut::<NSMutableData, NSMutableData>(&mut obj);
446-
impls_as_ref::<NSMutableData, NSData>(&obj);
447-
impls_as_mut::<NSMutableData, NSData>(&mut obj);
448-
impls_as_ref::<NSMutableData, NSObject>(&obj);
449-
impls_as_mut::<NSMutableData, NSObject>(&mut obj);
450-
impls_as_ref::<NSMutableData, Object>(&obj);
451-
impls_as_mut::<NSMutableData, Object>(&mut obj);
452-
453-
impls_as_ref::<NSData, NSData>(&obj);
454-
impls_as_mut::<NSData, NSData>(&mut obj);
455-
impls_as_ref::<NSData, NSObject>(&obj);
456-
impls_as_mut::<NSData, NSObject>(&mut obj);
457-
impls_as_ref::<NSData, Object>(&obj);
458-
impls_as_mut::<NSData, Object>(&mut obj);
446+
impls_borrow::<Id<NSMutableData, Owned>, NSMutableData>(&obj);
447+
impls_borrow_mut::<Id<NSMutableData, Owned>, NSMutableData>(&mut obj);
448+
449+
impls_borrow::<NSMutableData, NSMutableData>(&obj);
450+
impls_borrow_mut::<NSMutableData, NSMutableData>(&mut obj);
451+
impls_borrow::<NSMutableData, NSData>(&obj);
452+
impls_borrow_mut::<NSMutableData, NSData>(&mut obj);
453+
impls_borrow::<NSMutableData, NSObject>(&obj);
454+
impls_borrow_mut::<NSMutableData, NSObject>(&mut obj);
455+
impls_borrow::<NSMutableData, Object>(&obj);
456+
impls_borrow_mut::<NSMutableData, Object>(&mut obj);
457+
458+
impls_borrow::<NSData, NSData>(&obj);
459+
impls_borrow_mut::<NSData, NSData>(&mut obj);
460+
impls_borrow::<NSData, NSObject>(&obj);
461+
impls_borrow_mut::<NSData, NSObject>(&mut obj);
462+
impls_borrow::<NSData, Object>(&obj);
463+
impls_borrow_mut::<NSData, Object>(&mut obj);
464+
465+
fn impls_as_ref<T: AsRef<U> + ?Sized, U: ?Sized>(_: &T) {}
466+
fn impls_as_mut<T: AsMut<U> + ?Sized, U: ?Sized>(_: &mut T) {}
459467

460468
impls_as_ref::<NSMutableData, [u8]>(&obj);
461469
impls_as_mut::<NSMutableData, [u8]>(&mut obj);

objc2-foundation/src/macros.rs

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
macro_rules! __impl_as_ref_as_mut {
1+
macro_rules! __impl_as_ref_borrow {
22
($name:ident<$($t:ident $(: $b:ident)?),*>,) => {};
33
($name:ident<$($t:ident $(: $b:ident)?),*>, $item:ty, $($tail:ty,)*) => {
44
impl<$($t $(: $b)?),*> AsRef<$item> for $name<$($t),*> {
@@ -17,7 +17,29 @@ macro_rules! __impl_as_ref_as_mut {
1717
}
1818
}
1919

20-
__impl_as_ref_as_mut!($name<$($t $(: $b)?),*>, $($tail,)*);
20+
// Borrow and BorrowMut are correct, since subclasses behaves
21+
// identical to the class they inherit (message sending doesn't care).
22+
//
23+
// In particular, `Eq`, `Ord` and `Hash` all give the same results
24+
// after borrow.
25+
26+
impl<$($t $(: $b)?),*> ::core::borrow::Borrow<$item> for $name<$($t),*> {
27+
#[inline]
28+
fn borrow(&self) -> &$item {
29+
// Triggers Deref coercion depending on return type
30+
&*self
31+
}
32+
}
33+
34+
impl<$($t $(: $b)?),*> ::core::borrow::BorrowMut<$item> for $name<$($t),*> {
35+
#[inline]
36+
fn borrow_mut(&mut self) -> &mut $item {
37+
// Triggers Deref coercion depending on return type
38+
&mut *self
39+
}
40+
}
41+
42+
__impl_as_ref_borrow!($name<$($t $(: $b)?),*>, $($tail,)*);
2143
};
2244
}
2345

@@ -127,7 +149,21 @@ macro_rules! object {
127149
}
128150
}
129151

130-
__impl_as_ref_as_mut!($name<$($t $(: $b)?),*>, $name<$($t),*>, $inherits, $($inheritance_rest,)*);
152+
impl<$($t $(: $b)?),*> AsRef<Self> for $name<$($t),*> {
153+
#[inline]
154+
fn as_ref(&self) -> &Self {
155+
self
156+
}
157+
}
158+
159+
impl<$($t $(: $b)?),*> AsMut<Self> for $name<$($t),*> {
160+
#[inline]
161+
fn as_mut(&mut self) -> &mut Self {
162+
self
163+
}
164+
}
165+
166+
__impl_as_ref_borrow!($name<$($t $(: $b)?),*>, $inherits, $($inheritance_rest,)*);
131167

132168
// Objective-C equality has approximately the same semantics as Rust
133169
// equality (although less aptly specified).

objc2-foundation/src/object.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,11 @@ mod tests {
5757
}
5858

5959
#[test]
60-
fn test_as_ref() {
61-
fn impls_as_ref<T: AsRef<U> + ?Sized, U: ?Sized>(_: &T) {}
62-
fn impls_as_mut<T: AsMut<U> + ?Sized, U: ?Sized>(_: &mut T) {}
60+
fn test_as_ref_borrow() {
61+
use core::borrow::{Borrow, BorrowMut};
62+
63+
fn impls_as_ref<T: AsRef<U> + Borrow<U> + ?Sized, U: ?Sized>(_: &T) {}
64+
fn impls_as_mut<T: AsMut<U> + BorrowMut<U> + ?Sized, U: ?Sized>(_: &mut T) {}
6365

6466
let mut obj = NSObject::new();
6567
impls_as_ref::<Id<NSObject, Owned>, NSObject>(&obj);

0 commit comments

Comments
 (0)