Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ jobs:
- name: Test macOS 10.15
os: macos-10.15
target: x86_64-apple-darwin
- name: Test macOS 11
- name: Test macOS 11 w. ui tests
os: macos-11
target: x86_64-apple-darwin
args: --features tests/ui
- name: Build macOS AArch64
os: macos-11
target: aarch64-apple-darwin
Expand All @@ -54,11 +55,12 @@ jobs:
target: x86_64-apple-darwin
# Oldest macOS version we support
sdk: 10.7
- name: Test macOS nightly
- name: Test macOS nightly w. ui tests
os: macos-latest
target: x86_64-apple-darwin
rust:
toolchain: nightly
args: --features tests/ui
- name: Build macOS 32bit
os: macos-10.15
target: i686-apple-darwin
Expand Down
10 changes: 0 additions & 10 deletions objc2-foundation/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,6 @@ unsafe impl<T: Sync + Send> Send for NSArray<T, Shared> {}
unsafe impl<T: Sync> Sync for NSArray<T, Owned> {}
unsafe impl<T: Send> Send for NSArray<T, Owned> {}

/// ```compile_fail
/// use objc2::rc::Shared;
/// use objc2::runtime::Object;
/// use objc2_foundation::NSArray;
/// fn needs_send_sync<T: Send + Sync>() {}
/// needs_send_sync::<NSArray<Object, Shared>>();
/// ```
#[cfg(doctest)]
pub struct NSArrayWithObjectNotSendSync;

object! {
// TODO: Ensure that this deref to NSArray is safe!
unsafe pub struct NSMutableArray<T, O: Ownership>: NSArray<T, O> {
Expand Down
13 changes: 0 additions & 13 deletions objc2-foundation/src/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,6 @@ object! {
unsafe pub struct NSObject: Object;
}

/// ```compile_fail
/// use objc2_foundation::NSObject;
/// fn needs_sync<T: Sync>() {}
/// needs_sync::<NSObject>();
/// ```
/// ```compile_fail
/// use objc2_foundation::NSObject;
/// fn needs_send<T: Send>() {}
/// needs_send::<NSObject>();
/// ```
#[cfg(doctest)]
pub struct NSObjectNotSendNorSync;

impl NSObject {
unsafe_def_fn!(pub fn new -> Owned);

Expand Down
18 changes: 0 additions & 18 deletions objc2-foundation/src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,6 @@ impl NSString {
}

/// TODO
///
/// ```compile_fail
/// # use objc2::rc::autoreleasepool;
/// # use objc2_foundation::NSString;
/// autoreleasepool(|pool| {
/// let ns_string = NSString::new();
/// let s = ns_string.as_str(pool);
/// drop(ns_string);
/// println!("{}", s);
/// });
/// ```
///
/// ```compile_fail
/// # use objc2::rc::autoreleasepool;
/// # use objc2_foundation::NSString;
/// let ns_string = NSString::new();
/// let s = autoreleasepool(|pool| ns_string.as_str(pool));
/// ```
pub fn as_str<'r, 's: 'r, 'p: 'r>(&'s self, pool: &'p AutoreleasePool) -> &'r str {
// This is necessary until `auto` types stabilizes.
pool.__verify_is_inner();
Expand Down
8 changes: 0 additions & 8 deletions objc2-foundation/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,14 +110,6 @@ impl<T: 'static + Copy + Encode + fmt::Display> fmt::Display for NSValue<T> {
}
}

/// ```compile_fail
/// use objc2_foundation::NSValue;
/// fn needs_eq<T: Eq>() {}
/// needs_eq::<NSValue<f32>>();
/// ```
#[cfg(doctest)]
pub struct NSValueFloatNotEq;

#[cfg(test)]
mod tests {
use alloc::format;
Expand Down
18 changes: 0 additions & 18 deletions objc2/src/rc/autorelease.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,6 @@ pub struct AutoreleasePool {
p: PhantomData<*mut UnsafeCell<c_void>>,
}

/// ```
/// use objc2::rc::AutoreleasePool;
/// fn needs_nothing<T>() {}
/// needs_nothing::<AutoreleasePool>();
/// ```
/// ```compile_fail
/// use objc2::rc::AutoreleasePool;
/// fn needs_sync<T: Sync>() {}
/// needs_sync::<AutoreleasePool>();
/// ```
/// ```compile_fail
/// use objc2::rc::AutoreleasePool;
/// fn needs_send<T: Send>() {}
/// needs_send::<AutoreleasePool>();
/// ```
#[cfg(doctest)]
pub struct AutoreleasePoolNotSendNorSync;

#[cfg(all(debug_assertions, not(feature = "unstable_autoreleasesafe")))]
thread_local! {
/// We track the thread's pools to verify that object lifetimes are only
Expand Down
18 changes: 0 additions & 18 deletions objc2/src/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,24 +613,6 @@ impl Object {
// objc_removeAssociatedObjects
}

/// ```
/// use objc2::runtime::Object;
/// fn needs_nothing<T: ?Sized>() {}
/// needs_nothing::<Object>();
/// ```
/// ```compile_fail
/// use objc2::runtime::Object;
/// fn needs_sync<T: ?Sized + Sync>() {}
/// needs_sync::<Object>();
/// ```
/// ```compile_fail
/// use objc2::runtime::Object;
/// fn needs_send<T: ?Sized + Send>() {}
/// needs_send::<Object>();
/// ```
#[cfg(doctest)]
pub struct ObjectNotSendNorSync;

unsafe impl RefEncode for Object {
const ENCODING_REF: Encoding<'static> = Encoding::Object;
}
Expand Down
14 changes: 14 additions & 0 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,26 @@ license = "MIT"

build = "build.rs"

[features]
# Enable UI tests
#
# These are not enabled by default because trybuild doesn't pass feature flags
# (like --features gnustep-1-9) to its cargo invocation, and hence they don't
# always work.
#
# Also, they're slower than most tests.
ui = ["trybuild"]

[dependencies]
block2 = { path = "../block2" }
block-sys = { path = "../block-sys" }
objc-sys = { path = "../objc-sys" }
objc2 = { path = "../objc2" }
objc2-encode = { path = "../objc2-encode" }
objc2-foundation = { path = "../objc2-foundation" }

# Put here instead of dev-dependencies because we want to make it optional
trybuild = { version = "1.0", optional = true }

[build-dependencies]
cc = "1.0"
Expand Down
7 changes: 7 additions & 0 deletions tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,11 @@ mod tests {
let block = block.copy();
assert_eq!(invoke_large_struct_block(&block, data), new_data);
}

#[test]
#[cfg(feature = "ui")]
fn ui() {
let t = trybuild::TestCases::new();
t.compile_fail("ui/*.rs");
}
}
12 changes: 12 additions & 0 deletions tests/ui/autoreleasepool_not_send_sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//! Test that AutoreleasePool is not Send and Sync, because it internally
//! works with thread locals.

use objc2::rc::AutoreleasePool;

fn needs_sync<T: ?Sized + Sync>() {}
fn needs_send<T: ?Sized + Send>() {}

fn main() {
needs_sync::<AutoreleasePool>();
needs_send::<AutoreleasePool>();
}
57 changes: 57 additions & 0 deletions tests/ui/autoreleasepool_not_send_sync.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
error[E0277]: `*mut c_void` cannot be shared between threads safely
--> ui/autoreleasepool_not_send_sync.rs:10:5
|
10 | needs_sync::<AutoreleasePool>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut c_void` cannot be shared between threads safely
|
= help: within `AutoreleasePool`, the trait `Sync` is not implemented for `*mut c_void`
= note: required because it appears within the type `AutoreleasePool`
note: required by a bound in `needs_sync`
--> ui/autoreleasepool_not_send_sync.rs:6:27
|
6 | fn needs_sync<T: ?Sized + Sync>() {}
| ^^^^ required by this bound in `needs_sync`

error[E0277]: `*mut UnsafeCell<c_void>` cannot be shared between threads safely
--> ui/autoreleasepool_not_send_sync.rs:10:5
|
10 | needs_sync::<AutoreleasePool>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut UnsafeCell<c_void>` cannot be shared between threads safely
|
= help: within `AutoreleasePool`, the trait `Sync` is not implemented for `*mut UnsafeCell<c_void>`
= note: required because it appears within the type `PhantomData<*mut UnsafeCell<c_void>>`
= note: required because it appears within the type `AutoreleasePool`
note: required by a bound in `needs_sync`
--> ui/autoreleasepool_not_send_sync.rs:6:27
|
6 | fn needs_sync<T: ?Sized + Sync>() {}
| ^^^^ required by this bound in `needs_sync`

error[E0277]: `*mut c_void` cannot be sent between threads safely
--> ui/autoreleasepool_not_send_sync.rs:11:5
|
11 | needs_send::<AutoreleasePool>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut c_void` cannot be sent between threads safely
|
= help: within `AutoreleasePool`, the trait `Send` is not implemented for `*mut c_void`
= note: required because it appears within the type `AutoreleasePool`
note: required by a bound in `needs_send`
--> ui/autoreleasepool_not_send_sync.rs:7:27
|
7 | fn needs_send<T: ?Sized + Send>() {}
| ^^^^ required by this bound in `needs_send`

error[E0277]: `*mut UnsafeCell<c_void>` cannot be sent between threads safely
--> ui/autoreleasepool_not_send_sync.rs:11:5
|
11 | needs_send::<AutoreleasePool>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut UnsafeCell<c_void>` cannot be sent between threads safely
|
= help: within `AutoreleasePool`, the trait `Send` is not implemented for `*mut UnsafeCell<c_void>`
= note: required because it appears within the type `PhantomData<*mut UnsafeCell<c_void>>`
= note: required because it appears within the type `AutoreleasePool`
note: required by a bound in `needs_send`
--> ui/autoreleasepool_not_send_sync.rs:7:27
|
7 | fn needs_send<T: ?Sized + Send>() {}
| ^^^^ required by this bound in `needs_send`
7 changes: 7 additions & 0 deletions tests/ui/global_block_not_encode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
use block2::global_block;

global_block! {
pub static BLOCK = |_b: Box<i32>| {};
}

fn main() {}
12 changes: 12 additions & 0 deletions tests/ui/global_block_not_encode.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0277]: the trait bound `Box<i32>: objc2_encode::encode::Encode` is not satisfied
--> ui/global_block_not_encode.rs:3:1
|
3 | / global_block! {
4 | | pub static BLOCK = |_b: Box<i32>| {};
5 | | }
| |_^ the trait `objc2_encode::encode::Encode` is not implemented for `Box<i32>`
|
= note: required because of the requirements on the impl of `objc2_encode::encode::EncodeArguments` for `(Box<i32>,)`
= note: required because of the requirements on the impl of `Sync` for `GlobalBlock<(Box<i32>,)>`
= note: shared static variables must have a type that implements `Sync`
= note: this error originates in the macro `global_block` (in Nightly builds, run with -Z macro-backtrace for more info)
10 changes: 10 additions & 0 deletions tests/ui/msg_send_no_return_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
//! Test that forgetting to annotate the return type fails
//! See https://github.com/SSheldon/rust-objc/issues/62
use objc2::{class, msg_send};

fn main() {
unsafe {
let cls = class!(NSObject);
msg_send![cls, new];
}
}
7 changes: 7 additions & 0 deletions tests/ui/msg_send_no_return_type.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
error[E0282]: type annotations needed
--> ui/msg_send_no_return_type.rs:8:9
|
8 | msg_send![cls, new];
| ^^^^^^^^^^^^^^^^^^^ consider giving `result` a type
|
= note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)
9 changes: 9 additions & 0 deletions tests/ui/msg_send_not_encode.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Test that return types that are not `Encode` are not accepted.
use objc2::{class, msg_send};

fn main() {
unsafe {
let cls = class!(NSData);
let _: Vec<u8> = msg_send![cls, new];
}
}
12 changes: 12 additions & 0 deletions tests/ui/msg_send_not_encode.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
error[E0277]: the trait bound `Vec<u8>: Encode` is not satisfied
--> ui/msg_send_not_encode.rs:7:26
|
7 | let _: Vec<u8> = msg_send![cls, new];
| ^^^^^^^^^^^^^^^^^^^ the trait `Encode` is not implemented for `Vec<u8>`
|
note: required by a bound in `send_message`
--> $WORKSPACE/objc2/src/message/mod.rs
|
| R: Encode,
| ^^^^^^ required by this bound in `send_message`
= note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)
6 changes: 6 additions & 0 deletions tests/ui/msg_send_only_message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//! Test that messages can only be sent to objects.
use objc2::msg_send;

fn main() {
unsafe { msg_send![1, new] };
}
13 changes: 13 additions & 0 deletions tests/ui/msg_send_only_message.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0277]: the trait bound `{integer}: MessageReceiver` is not satisfied
--> ui/msg_send_only_message.rs:5:14
|
5 | unsafe { msg_send![1, new] };
| ^^^^^^^^^^^^^^^^^ the trait `MessageReceiver` is not implemented for `{integer}`
|
= help: the following implementations were found:
<&'a T as MessageReceiver>
<&'a mut T as MessageReceiver>
<*const T as MessageReceiver>
<*mut T as MessageReceiver>
and 3 others
= note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)
11 changes: 11 additions & 0 deletions tests/ui/nsarray_bound_not_send_sync.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use objc2::rc::Shared;
use objc2::runtime::Object;
use objc2_foundation::NSArray;

fn needs_sync<T: ?Sized + Sync>() {}
fn needs_send<T: ?Sized + Send>() {}

fn main() {
needs_sync::<NSArray<Object, Shared>>();
needs_send::<NSArray<Object, Shared>>();
}
Loading