Skip to content

Commit 0365ef4

Browse files
authored
Merge pull request #351 from madsmtm/encode-unsafecell
Implement `Encode` and `RefEncode` for `UnsafeCell` and `Cell`
2 parents dac2bc1 + c00d765 commit 0365ef4

File tree

3 files changed

+68
-11
lines changed

3 files changed

+68
-11
lines changed

crates/objc2/src/encode/mod.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
//! method argument, but is a very common return type, and hence implements
6060
//! [`Encode`].
6161
62+
use core::cell::{Cell, UnsafeCell};
6263
use core::ffi::c_void;
6364
use core::mem::{self, ManuallyDrop, MaybeUninit};
6465
use core::num::{
@@ -484,11 +485,15 @@ encode_impls_transparent! {
484485
// TODO: With specialization: `impl Encode for ManuallyDrop<Box<T>>`
485486
ManuallyDrop<T: ?Sized>,
486487

488+
// SAFETY: Guaranteed to have the same in-memory representation `T`.
489+
//
487490
// The fact that this has `repr(no_niche)` has no effect on us, since we
488491
// don't unconditionally implement `Encode` generically over `Option`.
489492
// (e.g. an `Option<UnsafeCell<&u8>>` impl is not available).
490-
// The inner field is not public, so may not be stable.
491-
// TODO: UnsafeCell<T>,
493+
UnsafeCell<T: ?Sized>,
494+
495+
// SAFETY: Guaranteed to have the same layout as `UnsafeCell<T>`.
496+
Cell<T: ?Sized>,
492497

493498
// The inner field is not public, so may not be safe.
494499
// TODO: Pin<T>,
@@ -499,9 +504,6 @@ encode_impls_transparent! {
499504
// SAFETY: Guaranteed to have the same layout and ABI as `T`.
500505
Wrapping<T>,
501506

502-
// It might have requirements that would disourage this impl?
503-
// TODO: Cell<T>
504-
505507
// TODO: Types that need to be made repr(transparent) first:
506508
// - core::cell::Ref?
507509
// - core::cell::RefCell?
@@ -702,13 +704,13 @@ mod tests {
702704
assert_eq!(<ManuallyDrop<Option<&u8>>>::ENCODING, u8::ENCODING_REF);
703705
assert_eq!(<&ManuallyDrop<Option<&u8>>>::ENCODING, <&&u8>::ENCODING);
704706

705-
// assert_eq!(<UnsafeCell<u8>>::ENCODING, u8::ENCODING);
707+
assert_eq!(<UnsafeCell<u8>>::ENCODING, u8::ENCODING);
708+
assert_eq!(<UnsafeCell<&u8>>::ENCODING, <&u8>::ENCODING);
709+
assert_eq!(<Cell<u8>>::ENCODING, u8::ENCODING);
710+
assert_eq!(<Cell<&u8>>::ENCODING, <&u8>::ENCODING);
706711
// assert_eq!(<Pin<u8>>::ENCODING, u8::ENCODING);
707712
assert_eq!(<MaybeUninit<u8>>::ENCODING, u8::ENCODING);
708713
assert_eq!(<Wrapping<u8>>::ENCODING, u8::ENCODING);
709-
710-
// Shouldn't compile
711-
// assert_eq!(<Option<UnsafeCell<&u8>>>::ENCODING, <&u8>::ENCODING);
712714
}
713715

714716
#[test]

crates/test-ui/ui/not_encode.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Verify that certain things we don't want to be encode aren't.
2+
use core::cell::{Cell, UnsafeCell};
23
use core::ffi::c_void;
34

45
use objc2::encode::Encode;
@@ -22,4 +23,12 @@ fn main() {
2223
is_encode::<fn(i32, ())>();
2324

2425
is_encode::<&Sel>();
26+
27+
// This should compile
28+
is_encode::<UnsafeCell<&u8>>();
29+
// But this mustn't
30+
is_encode::<Option<UnsafeCell<&u8>>>();
31+
32+
// Same
33+
is_encode::<Option<Cell<&u8>>>();
2534
}

crates/test-ui/ui/not_encode.stderr

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,52 @@ note: required by a bound in `is_encode`
224224
| ^^^^^^ required by this bound in `is_encode`
225225
help: consider removing the leading `&`-reference
226226
|
227-
24 - is_encode::<&Sel>();
228-
24 + is_encode::<Sel>();
227+
25 - is_encode::<&Sel>();
228+
25 + is_encode::<Sel>();
229229
|
230+
231+
error[E0277]: the trait bound `UnsafeCell<&u8>: OptionEncode` is not satisfied
232+
--> ui/not_encode.rs
233+
|
234+
| is_encode::<Option<UnsafeCell<&u8>>>();
235+
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `OptionEncode` is not implemented for `UnsafeCell<&u8>`
236+
|
237+
= help: the following other types implement trait `OptionEncode`:
238+
&'a T
239+
&'a mut T
240+
NonNull<T>
241+
NonNull<c_void>
242+
NonZeroI16
243+
NonZeroI32
244+
NonZeroI64
245+
NonZeroI8
246+
and $N others
247+
= note: required for `Option<UnsafeCell<&u8>>` to implement `Encode`
248+
note: required by a bound in `is_encode`
249+
--> ui/not_encode.rs
250+
|
251+
| fn is_encode<T: Encode>() {}
252+
| ^^^^^^ required by this bound in `is_encode`
253+
254+
error[E0277]: the trait bound `Cell<&u8>: OptionEncode` is not satisfied
255+
--> ui/not_encode.rs
256+
|
257+
| is_encode::<Option<Cell<&u8>>>();
258+
| ^^^^^^^^^^^^^^^^^ the trait `OptionEncode` is not implemented for `Cell<&u8>`
259+
|
260+
= help: the following other types implement trait `OptionEncode`:
261+
&'a T
262+
&'a mut T
263+
NonNull<T>
264+
NonNull<c_void>
265+
NonZeroI16
266+
NonZeroI32
267+
NonZeroI64
268+
NonZeroI8
269+
and $N others
270+
= note: required for `Option<Cell<&u8>>` to implement `Encode`
271+
note: required by a bound in `is_encode`
272+
--> ui/not_encode.rs
273+
|
274+
| fn is_encode<T: Encode>() {}
275+
| ^^^^^^ required by this bound in `is_encode`

0 commit comments

Comments
 (0)