Skip to content

Commit 04087bb

Browse files
authored
Merge pull request #98 from madsmtm/unsized
Relax `Sized` bounds where easily possible
2 parents 4c5b298 + 82bc5c8 commit 04087bb

14 files changed

+83
-74
lines changed

objc2-foundation/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2121
### Removed
2222
* **BREAKING**: Removed associated `Ownership` type from `INSObject`; instead,
2323
it is present on the types that actually need it (for example `NSCopying`).
24+
* **BREAKING**: Removed `Sized` bound on `INSObject`.
2425

2526
### Fixed
2627
* Soundness issue with `NSValue`, `NSDictionary`, `NSArray` and

objc2-foundation/src/array.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use super::{
1414
NSRange,
1515
};
1616

17-
unsafe fn from_refs<A: INSArray>(refs: &[&A::Item]) -> Id<A, A::Ownership> {
17+
unsafe fn from_refs<A: INSArray + ?Sized>(refs: &[&A::Item]) -> Id<A, A::Ownership> {
1818
let cls = A::class();
1919
let obj: *mut A = unsafe { msg_send![cls, alloc] };
2020
let obj: *mut A = unsafe {

objc2-foundation/src/dictionary.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use super::{INSCopying, INSFastEnumeration, INSObject, NSArray, NSEnumerator};
1111

1212
unsafe fn from_refs<D, T>(keys: &[&T], vals: &[&D::Value]) -> Id<D, Shared>
1313
where
14-
D: INSDictionary,
15-
T: INSCopying<Output = D::Key>,
14+
D: INSDictionary + ?Sized,
15+
T: INSCopying<Output = D::Key> + ?Sized,
1616
{
1717
let cls = D::class();
1818
let count = min(keys.len(), vals.len());

objc2-foundation/src/enumerator.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ unsafe impl<T: INSObject> RefEncode for NSFastEnumerationState<T> {
9494
const ENCODING_REF: Encoding<'static> = Encoding::Pointer(&Self::ENCODING);
9595
}
9696

97-
fn enumerate<'a, 'b: 'a, C: INSFastEnumeration>(
97+
fn enumerate<'a, 'b: 'a, C: INSFastEnumeration + ?Sized>(
9898
object: &'b C,
9999
state: &mut NSFastEnumerationState<C::Item>,
100100
buf: &'a mut [*const C::Item],
@@ -119,7 +119,7 @@ fn enumerate<'a, 'b: 'a, C: INSFastEnumeration>(
119119

120120
const FAST_ENUM_BUF_SIZE: usize = 16;
121121

122-
pub struct NSFastEnumerator<'a, C: 'a + INSFastEnumeration> {
122+
pub struct NSFastEnumerator<'a, C: 'a + INSFastEnumeration + ?Sized> {
123123
object: &'a C,
124124

125125
ptr: *const *const C::Item,
@@ -129,7 +129,7 @@ pub struct NSFastEnumerator<'a, C: 'a + INSFastEnumeration> {
129129
buf: [*const C::Item; FAST_ENUM_BUF_SIZE],
130130
}
131131

132-
impl<'a, C: INSFastEnumeration> NSFastEnumerator<'a, C> {
132+
impl<'a, C: INSFastEnumeration + ?Sized> NSFastEnumerator<'a, C> {
133133
fn new(object: &'a C) -> Self {
134134
Self {
135135
object,
@@ -174,7 +174,7 @@ impl<'a, C: INSFastEnumeration> NSFastEnumerator<'a, C> {
174174
}
175175
}
176176

177-
impl<'a, C: INSFastEnumeration> Iterator for NSFastEnumerator<'a, C> {
177+
impl<'a, C: INSFastEnumeration + ?Sized> Iterator for NSFastEnumerator<'a, C> {
178178
type Item = &'a C::Item;
179179

180180
fn next(&mut self) -> Option<&'a C::Item> {

objc2-foundation/src/object.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@ use objc2::Message;
88

99
use super::NSString;
1010

11-
// The Sized bound is unfortunate; ideally, Objective-C objects would not be
12-
// treated as Sized. However, rust won't allow casting a dynamically-sized
13-
// type pointer to an Object pointer, because dynamically-sized types can have
14-
// fat pointers (two words) instead of real pointers.
15-
pub unsafe trait INSObject: Sized + Message {
11+
pub unsafe trait INSObject: Message {
1612
fn class() -> &'static Class;
1713

1814
fn hash_code(&self) -> usize {

objc2/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
3636
- `Class::instance_variables`
3737
- `Protocol::protocols`
3838
- `Protocol::adopted_protocols`
39+
* Relaxed `Sized` bound on `rc::Id` and `rc::WeakId` to prepare for
40+
`extern type` support.
41+
* **BREAKING**: Relaxed `Sized` bound on `rc::SliceId` and `rc::DefaultId`.
3942

4043
### Removed
4144
* **BREAKING**: Removed the raw FFI functions from the `runtime` module. These

objc2/src/declare.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ use crate::{ffi, Encode, EncodeArguments, Encoding, Message};
4545
/// Types that can be used as the implementation of an Objective-C method.
4646
pub trait MethodImplementation {
4747
/// The callee type of the method.
48-
type Callee: Message;
48+
type Callee: Message + ?Sized;
4949
/// The return type of the method.
5050
type Ret: Encode;
5151
/// The argument types of the method.
@@ -59,7 +59,7 @@ macro_rules! method_decl_impl {
5959
(-$s:ident, $r:ident, $f:ty, $($t:ident),*) => (
6060
impl<$s, $r, $($t),*> MethodImplementation for $f
6161
where
62-
$s: Message,
62+
$s: Message + ?Sized,
6363
$r: Encode,
6464
$($t: Encode,)*
6565
{

objc2/src/message/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ pub(crate) mod private {
7979
impl<'a, T: Message + ?Sized> Sealed for &'a T {}
8080
impl<'a, T: Message + ?Sized> Sealed for &'a mut T {}
8181
impl<T: Message + ?Sized> Sealed for NonNull<T> {}
82-
impl<T: Message, O: Ownership> Sealed for Id<T, O> {}
82+
impl<T: Message + ?Sized, O: Ownership> Sealed for Id<T, O> {}
8383

8484
impl<T: MessageReceiver + ?Sized> Sealed for ManuallyDrop<T> {}
8585
}
@@ -248,7 +248,7 @@ unsafe impl<T: Message + ?Sized> MessageReceiver for NonNull<T> {
248248
}
249249
}
250250

251-
unsafe impl<T: Message, O: Ownership> MessageReceiver for Id<T, O> {
251+
unsafe impl<T: Message + ?Sized, O: Ownership> MessageReceiver for Id<T, O> {
252252
#[inline]
253253
fn as_raw_receiver(&self) -> *mut Object {
254254
// TODO: Maybe don't dereference here, just to be safe?

objc2/src/rc/autorelease.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ impl AutoreleasePool {
101101
/// the lifetime is bound to the pool instead of being unbounded.
102102
#[inline]
103103
#[allow(clippy::needless_lifetimes)]
104-
pub unsafe fn ptr_as_ref<'p, T>(&'p self, ptr: *const T) -> &'p T {
104+
pub unsafe fn ptr_as_ref<'p, T: ?Sized>(&'p self, ptr: *const T) -> &'p T {
105105
self.__verify_is_inner();
106106
// SAFETY: Checked by the caller
107107
unsafe { &*ptr }
@@ -122,7 +122,7 @@ impl AutoreleasePool {
122122
#[inline]
123123
#[allow(clippy::needless_lifetimes)]
124124
#[allow(clippy::mut_from_ref)]
125-
pub unsafe fn ptr_as_mut<'p, T>(&'p self, ptr: *mut T) -> &'p mut T {
125+
pub unsafe fn ptr_as_mut<'p, T: ?Sized>(&'p self, ptr: *mut T) -> &'p mut T {
126126
self.__verify_is_inner();
127127
// SAFETY: Checked by the caller
128128
unsafe { &mut *ptr }
@@ -202,7 +202,7 @@ auto_trait! {
202202
}
203203

204204
#[cfg(not(feature = "unstable_autoreleasesafe"))]
205-
unsafe impl<T> AutoreleaseSafe for T {}
205+
unsafe impl<T: ?Sized> AutoreleaseSafe for T {}
206206

207207
#[cfg(feature = "unstable_autoreleasesafe")]
208208
impl !AutoreleaseSafe for AutoreleasePool {}

objc2/src/rc/id.rs

+25-17
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ use crate::Message;
5353
/// do so. If you need to run some code when the object is destroyed,
5454
/// implement the `dealloc` method instead.
5555
///
56+
/// This allows `?Sized` types `T`, but the intention is to only support when
57+
/// `T` is an `extern type` (yet unstable).
58+
///
5659
/// # Examples
5760
///
5861
/// ```no_run
@@ -95,9 +98,9 @@ use crate::Message;
9598
/// ```
9699
#[repr(transparent)]
97100
// TODO: Figure out if `Message` bound on `T` would be better here?
98-
// TODO: Add `?Sized + ptr::Thin` bound on `T` to allow for extern types
101+
// TODO: Add `ptr::Thin` bound on `T` to allow for only extern types
99102
// TODO: Consider changing the name of Id -> Retain
100-
pub struct Id<T, O: Ownership> {
103+
pub struct Id<T: ?Sized, O: Ownership> {
101104
/// A pointer to the contained object. The pointer is always retained.
102105
///
103106
/// It is important that this is `NonNull`, since we want to dereference
@@ -116,8 +119,7 @@ pub struct Id<T, O: Ownership> {
116119
own: PhantomData<O>,
117120
}
118121

119-
// TODO: Maybe make most of these functions "associated" functions instead?
120-
impl<T: Message, O: Ownership> Id<T, O> {
122+
impl<T: Message + ?Sized, O: Ownership> Id<T, O> {
121123
/// Constructs an [`Id`] to an object that already has +1 retain count.
122124
///
123125
/// This is useful when you have a retain count that has been handed off
@@ -171,7 +173,10 @@ impl<T: Message, O: Ownership> Id<T, O> {
171173
own: PhantomData,
172174
}
173175
}
176+
}
174177

178+
// TODO: Add ?Sized bound
179+
impl<T: Message, O: Ownership> Id<T, O> {
175180
/// Retains the given object pointer.
176181
///
177182
/// This is useful when you have been given a pointer to an object from
@@ -254,6 +259,7 @@ impl<T: Message, O: Ownership> Id<T, O> {
254259
// }
255260
// }
256261

262+
// TODO: Add ?Sized bound
257263
impl<T: Message> Id<T, Owned> {
258264
/// Autoreleases the owned [`Id`], returning a mutable reference bound to
259265
/// the pool.
@@ -291,6 +297,7 @@ impl<T: Message> Id<T, Owned> {
291297
}
292298
}
293299

300+
// TODO: Add ?Sized bound
294301
impl<T: Message> Id<T, Shared> {
295302
/// Autoreleases the shared [`Id`], returning an aliased reference bound
296303
/// to the pool.
@@ -308,7 +315,7 @@ impl<T: Message> Id<T, Shared> {
308315
}
309316
}
310317

311-
impl<T: Message> From<Id<T, Owned>> for Id<T, Shared> {
318+
impl<T: Message + ?Sized> From<Id<T, Owned>> for Id<T, Shared> {
312319
/// Downgrade from an owned to a shared [`Id`], allowing it to be cloned.
313320
#[inline]
314321
fn from(obj: Id<T, Owned>) -> Self {
@@ -318,6 +325,7 @@ impl<T: Message> From<Id<T, Owned>> for Id<T, Shared> {
318325
}
319326
}
320327

328+
// TODO: Add ?Sized bound
321329
impl<T: Message> Clone for Id<T, Shared> {
322330
/// Makes a clone of the shared object.
323331
///
@@ -338,7 +346,7 @@ impl<T: Message> Clone for Id<T, Shared> {
338346
/// borrowed data.
339347
///
340348
/// [dropck_eyepatch]: https://doc.rust-lang.org/nightly/nomicon/dropck.html#an-escape-hatch
341-
impl<T, O: Ownership> Drop for Id<T, O> {
349+
impl<T: ?Sized, O: Ownership> Drop for Id<T, O> {
342350
/// Releases the retained object.
343351
///
344352
/// The contained object's destructor (if it has one) is never run!
@@ -363,25 +371,25 @@ impl<T, O: Ownership> Drop for Id<T, O> {
363371
/// clone a `Id<T, Shared>`, send it to another thread, and drop the clone
364372
/// last, making `dealloc` get called on the other thread, and violate
365373
/// `T: !Send`.
366-
unsafe impl<T: Sync + Send> Send for Id<T, Shared> {}
374+
unsafe impl<T: Sync + Send + ?Sized> Send for Id<T, Shared> {}
367375

368376
/// The `Sync` implementation requires `T: Sync` because `&Id<T, Shared>` give
369377
/// access to `&T`.
370378
///
371379
/// Additiontally, it requires `T: Send`, because if `T: !Send`, you could
372380
/// clone a `&Id<T, Shared>` from another thread, and drop the clone last,
373381
/// making `dealloc` get called on the other thread, and violate `T: !Send`.
374-
unsafe impl<T: Sync + Send> Sync for Id<T, Shared> {}
382+
unsafe impl<T: Sync + Send + ?Sized> Sync for Id<T, Shared> {}
375383

376384
/// `Id<T, Owned>` are `Send` if `T` is `Send` because they give the same
377385
/// access as having a T directly.
378-
unsafe impl<T: Send> Send for Id<T, Owned> {}
386+
unsafe impl<T: Send + ?Sized> Send for Id<T, Owned> {}
379387

380388
/// `Id<T, Owned>` are `Sync` if `T` is `Sync` because they give the same
381389
/// access as having a `T` directly.
382-
unsafe impl<T: Sync> Sync for Id<T, Owned> {}
390+
unsafe impl<T: Sync + ?Sized> Sync for Id<T, Owned> {}
383391

384-
impl<T, O: Ownership> Deref for Id<T, O> {
392+
impl<T: ?Sized, O: Ownership> Deref for Id<T, O> {
385393
type Target = T;
386394

387395
/// Obtain an immutable reference to the object.
@@ -393,7 +401,7 @@ impl<T, O: Ownership> Deref for Id<T, O> {
393401
}
394402
}
395403

396-
impl<T> DerefMut for Id<T, Owned> {
404+
impl<T: ?Sized> DerefMut for Id<T, Owned> {
397405
/// Obtain a mutable reference to the object.
398406
#[inline]
399407
fn deref_mut(&mut self) -> &mut T {
@@ -404,7 +412,7 @@ impl<T> DerefMut for Id<T, Owned> {
404412
}
405413
}
406414

407-
impl<T, O: Ownership> fmt::Pointer for Id<T, O> {
415+
impl<T: ?Sized, O: Ownership> fmt::Pointer for Id<T, O> {
408416
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
409417
fmt::Pointer::fmt(&self.ptr.as_ptr(), f)
410418
}
@@ -414,15 +422,15 @@ impl<T, O: Ownership> fmt::Pointer for Id<T, O> {
414422
//
415423
// See https://doc.rust-lang.org/1.54.0/src/alloc/boxed.rs.html#1652-1675
416424
// and the `Arc` implementation.
417-
impl<T, O: Ownership> Unpin for Id<T, O> {}
425+
impl<T: ?Sized, O: Ownership> Unpin for Id<T, O> {}
418426

419-
impl<T: RefUnwindSafe, O: Ownership> RefUnwindSafe for Id<T, O> {}
427+
impl<T: RefUnwindSafe + ?Sized, O: Ownership> RefUnwindSafe for Id<T, O> {}
420428

421429
// Same as `Arc<T>`.
422-
impl<T: RefUnwindSafe> UnwindSafe for Id<T, Shared> {}
430+
impl<T: RefUnwindSafe + ?Sized> UnwindSafe for Id<T, Shared> {}
423431

424432
// Same as `Box<T>`.
425-
impl<T: UnwindSafe> UnwindSafe for Id<T, Owned> {}
433+
impl<T: UnwindSafe + ?Sized> UnwindSafe for Id<T, Owned> {}
426434

427435
#[cfg(test)]
428436
mod tests {

0 commit comments

Comments
 (0)