Skip to content

Commit ad61d93

Browse files
committed
Implement Encode and RefEncode for UnsafeCell
1 parent 0a0c861 commit ad61d93

File tree

3 files changed

+121
-6
lines changed

3 files changed

+121
-6
lines changed

crates/objc2-encode/src/encode.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use core::cell::UnsafeCell;
12
use core::ffi::c_void;
23
use core::mem::{self, ManuallyDrop, MaybeUninit};
34
use core::num::{
@@ -451,11 +452,12 @@ encode_impls_transparent! {
451452
// TODO: With specialization: `impl Encode for ManuallyDrop<Box<T>>`
452453
ManuallyDrop<T: ?Sized>,
453454

455+
// SAFETY: Guaranteed to have the same in-memory representation `T`.
456+
//
454457
// The fact that this has `repr(no_niche)` has no effect on us, since we
455458
// don't unconditionally implement `Encode` generically over `Option`.
456459
// (e.g. an `Option<UnsafeCell<&u8>>` impl is not available).
457-
// The inner field is not public, so may not be stable.
458-
// TODO: UnsafeCell<T>,
460+
UnsafeCell<T: ?Sized>,
459461

460462
// The inner field is not public, so may not be safe.
461463
// TODO: Pin<T>,
@@ -791,13 +793,10 @@ mod tests {
791793
assert_eq!(<ManuallyDrop<Option<&u8>>>::ENCODING, u8::ENCODING_REF);
792794
assert_eq!(<&ManuallyDrop<Option<&u8>>>::ENCODING, <&&u8>::ENCODING);
793795

794-
// assert_eq!(<UnsafeCell<u8>>::ENCODING, u8::ENCODING);
796+
assert_eq!(<UnsafeCell<u8>>::ENCODING, u8::ENCODING);
795797
// assert_eq!(<Pin<u8>>::ENCODING, u8::ENCODING);
796798
assert_eq!(<MaybeUninit<u8>>::ENCODING, u8::ENCODING);
797799
assert_eq!(<Wrapping<u8>>::ENCODING, u8::ENCODING);
798-
799-
// Shouldn't compile
800-
// assert_eq!(<Option<UnsafeCell<&u8>>>::ENCODING, <&u8>::ENCODING);
801800
}
802801

803802
#[test]

crates/test-ui/ui/not_encode.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
//! Verify that certain things we don't want to be encode aren't.
2+
use core::cell::UnsafeCell;
3+
use core::ffi::c_void;
4+
5+
use objc2::encode::Encode;
6+
use objc2::runtime::Sel;
7+
8+
fn is_encode<T: Encode>() {}
9+
10+
fn main() {
11+
is_encode::<&Sel>();
12+
is_encode::<&c_void>();
13+
is_encode::<&()>();
14+
is_encode::<fn() -> &'static ()>();
15+
16+
// This should be encode
17+
is_encode::<UnsafeCell<&u8>>();
18+
// But this shouldn't be
19+
is_encode::<Option<UnsafeCell<&u8>>>();
20+
}

crates/test-ui/ui/not_encode.stderr

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
error[E0277]: the trait bound `objc2::runtime::Sel: RefEncode` is not satisfied
2+
--> ui/not_encode.rs
3+
|
4+
| is_encode::<&Sel>();
5+
| ^^^^ the trait `RefEncode` is not implemented for `objc2::runtime::Sel`
6+
|
7+
= note: required for `&objc2::runtime::Sel` to implement `Encode`
8+
note: required by a bound in `is_encode`
9+
--> ui/not_encode.rs
10+
|
11+
| fn is_encode<T: Encode>() {}
12+
| ^^^^^^ required by this bound in `is_encode`
13+
help: consider removing the leading `&`-reference
14+
|
15+
11 - is_encode::<&Sel>();
16+
11 + is_encode::<Sel>();
17+
|
18+
19+
error[E0277]: the trait bound `c_void: RefEncode` is not satisfied
20+
--> ui/not_encode.rs
21+
|
22+
| is_encode::<&c_void>();
23+
| ^^^^^^^ the trait `RefEncode` is not implemented for `c_void`
24+
|
25+
= help: the following other types implement trait `RefEncode`:
26+
*const c_void
27+
*mut c_void
28+
= note: required for `&c_void` to implement `Encode`
29+
note: required by a bound in `is_encode`
30+
--> ui/not_encode.rs
31+
|
32+
| fn is_encode<T: Encode>() {}
33+
| ^^^^^^ required by this bound in `is_encode`
34+
35+
error[E0277]: the trait bound `(): RefEncode` is not satisfied
36+
--> ui/not_encode.rs
37+
|
38+
| is_encode::<&()>();
39+
| ^^^ the trait `RefEncode` is not implemented for `()`
40+
|
41+
= note: required for `&()` to implement `Encode`
42+
note: required by a bound in `is_encode`
43+
--> ui/not_encode.rs
44+
|
45+
| fn is_encode<T: Encode>() {}
46+
| ^^^^^^ required by this bound in `is_encode`
47+
help: consider removing the leading `&`-reference
48+
|
49+
13 - is_encode::<&()>();
50+
13 + is_encode::<()>();
51+
|
52+
53+
error[E0277]: the trait bound `fn() -> &'static (): Encode` is not satisfied
54+
--> ui/not_encode.rs
55+
|
56+
| is_encode::<fn() -> &'static ()>();
57+
| ^^^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `fn() -> &'static ()`
58+
|
59+
= help: the following other types implement trait `Encode`:
60+
extern "C" fn() -> Ret
61+
extern "C" fn(A) -> Ret
62+
extern "C" fn(A, ...) -> Ret
63+
extern "C" fn(A, B) -> Ret
64+
extern "C" fn(A, B, ...) -> Ret
65+
extern "C" fn(A, B, C) -> Ret
66+
extern "C" fn(A, B, C, ...) -> Ret
67+
extern "C" fn(A, B, C, D) -> Ret
68+
and $N others
69+
note: required by a bound in `is_encode`
70+
--> ui/not_encode.rs
71+
|
72+
| fn is_encode<T: Encode>() {}
73+
| ^^^^^^ required by this bound in `is_encode`
74+
75+
error[E0277]: the trait bound `UnsafeCell<&u8>: OptionEncode` is not satisfied
76+
--> ui/not_encode.rs
77+
|
78+
| is_encode::<Option<UnsafeCell<&u8>>>();
79+
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `OptionEncode` is not implemented for `UnsafeCell<&u8>`
80+
|
81+
= help: the following other types implement trait `OptionEncode`:
82+
&'a T
83+
&'a mut T
84+
NonNull<T>
85+
NonNull<c_void>
86+
NonZeroI16
87+
NonZeroI32
88+
NonZeroI64
89+
NonZeroI8
90+
and $N others
91+
= note: required for `Option<UnsafeCell<&u8>>` to implement `Encode`
92+
note: required by a bound in `is_encode`
93+
--> ui/not_encode.rs
94+
|
95+
| fn is_encode<T: Encode>() {}
96+
| ^^^^^^ required by this bound in `is_encode`

0 commit comments

Comments
 (0)