Skip to content

Commit

Permalink
Move some compile_fail doctests to UI tests
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed Jan 16, 2022
1 parent b4cbe20 commit ddf483a
Show file tree
Hide file tree
Showing 21 changed files with 389 additions and 85 deletions.
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
1 change: 1 addition & 0 deletions tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ 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 }
Expand Down
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)
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>>();
}
107 changes: 107 additions & 0 deletions tests/ui/nsarray_bound_not_send_sync.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
error[E0277]: `UnsafeCell<()>` cannot be shared between threads safely
--> ui/nsarray_bound_not_send_sync.rs:9:5
|
9 | needs_sync::<NSArray<Object, Shared>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<()>` cannot be shared between threads safely
|
= help: within `objc2::runtime::Object`, the trait `Sync` is not implemented for `UnsafeCell<()>`
= note: required because it appears within the type `(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)`
= note: required because it appears within the type `PhantomData<(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)>`
= note: required because it appears within the type `objc_object`
= note: required because it appears within the type `objc2::runtime::Object`
= note: required because of the requirements on the impl of `Sync` for `NSArray<objc2::runtime::Object, Shared>`
note: required by a bound in `needs_sync`
--> ui/nsarray_bound_not_send_sync.rs:5:27
|
5 | fn needs_sync<T: ?Sized + Sync>() {}
| ^^^^ required by this bound in `needs_sync`

error[E0277]: `*const UnsafeCell<()>` cannot be shared between threads safely
--> ui/nsarray_bound_not_send_sync.rs:9:5
|
9 | needs_sync::<NSArray<Object, Shared>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const UnsafeCell<()>` cannot be shared between threads safely
|
= help: within `objc2::runtime::Object`, the trait `Sync` is not implemented for `*const UnsafeCell<()>`
= note: required because it appears within the type `(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)`
= note: required because it appears within the type `PhantomData<(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)>`
= note: required because it appears within the type `objc_object`
= note: required because it appears within the type `objc2::runtime::Object`
= note: required because of the requirements on the impl of `Sync` for `NSArray<objc2::runtime::Object, Shared>`
note: required by a bound in `needs_sync`
--> ui/nsarray_bound_not_send_sync.rs:5:27
|
5 | fn needs_sync<T: ?Sized + Sync>() {}
| ^^^^ required by this bound in `needs_sync`

error[E0277]: `*const UnsafeCell<()>` cannot be sent between threads safely
--> ui/nsarray_bound_not_send_sync.rs:9:5
|
9 | needs_sync::<NSArray<Object, Shared>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const UnsafeCell<()>` cannot be sent between threads safely
|
= help: within `objc2::runtime::Object`, the trait `Send` is not implemented for `*const UnsafeCell<()>`
= note: required because it appears within the type `(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)`
= note: required because it appears within the type `PhantomData<(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)>`
= note: required because it appears within the type `objc_object`
= note: required because it appears within the type `objc2::runtime::Object`
= note: required because of the requirements on the impl of `Sync` for `NSArray<objc2::runtime::Object, Shared>`
note: required by a bound in `needs_sync`
--> ui/nsarray_bound_not_send_sync.rs:5:27
|
5 | fn needs_sync<T: ?Sized + Sync>() {}
| ^^^^ required by this bound in `needs_sync`

error[E0277]: `UnsafeCell<()>` cannot be shared between threads safely
--> ui/nsarray_bound_not_send_sync.rs:10:5
|
10 | needs_send::<NSArray<Object, Shared>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<()>` cannot be shared between threads safely
|
= help: within `objc2::runtime::Object`, the trait `Sync` is not implemented for `UnsafeCell<()>`
= note: required because it appears within the type `(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)`
= note: required because it appears within the type `PhantomData<(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)>`
= note: required because it appears within the type `objc_object`
= note: required because it appears within the type `objc2::runtime::Object`
= note: required because of the requirements on the impl of `Send` for `NSArray<objc2::runtime::Object, Shared>`
note: required by a bound in `needs_send`
--> ui/nsarray_bound_not_send_sync.rs:6:27
|
6 | fn needs_send<T: ?Sized + Send>() {}
| ^^^^ required by this bound in `needs_send`

error[E0277]: `*const UnsafeCell<()>` cannot be shared between threads safely
--> ui/nsarray_bound_not_send_sync.rs:10:5
|
10 | needs_send::<NSArray<Object, Shared>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const UnsafeCell<()>` cannot be shared between threads safely
|
= help: within `objc2::runtime::Object`, the trait `Sync` is not implemented for `*const UnsafeCell<()>`
= note: required because it appears within the type `(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)`
= note: required because it appears within the type `PhantomData<(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)>`
= note: required because it appears within the type `objc_object`
= note: required because it appears within the type `objc2::runtime::Object`
= note: required because of the requirements on the impl of `Send` for `NSArray<objc2::runtime::Object, Shared>`
note: required by a bound in `needs_send`
--> ui/nsarray_bound_not_send_sync.rs:6:27
|
6 | fn needs_send<T: ?Sized + Send>() {}
| ^^^^ required by this bound in `needs_send`

error[E0277]: `*const UnsafeCell<()>` cannot be sent between threads safely
--> ui/nsarray_bound_not_send_sync.rs:10:5
|
10 | needs_send::<NSArray<Object, Shared>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const UnsafeCell<()>` cannot be sent between threads safely
|
= help: within `objc2::runtime::Object`, the trait `Send` is not implemented for `*const UnsafeCell<()>`
= note: required because it appears within the type `(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)`
= note: required because it appears within the type `PhantomData<(UnsafeCell<()>, *const UnsafeCell<()>, PhantomPinned)>`
= note: required because it appears within the type `objc_object`
= note: required because it appears within the type `objc2::runtime::Object`
= note: required because of the requirements on the impl of `Send` for `NSArray<objc2::runtime::Object, Shared>`
note: required by a bound in `needs_send`
--> ui/nsarray_bound_not_send_sync.rs:6:27
|
6 | fn needs_send<T: ?Sized + Send>() {}
| ^^^^ required by this bound in `needs_send`
13 changes: 13 additions & 0 deletions tests/ui/nsstring_as_str_use_after_release.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! Test that the lifetime of `NSString::as_str` is bound to the string.

use objc2::rc::autoreleasepool;
use objc2_foundation::NSString;

fn main() {
autoreleasepool(|pool| {
let ns_string = NSString::new();
let s = ns_string.as_str(pool);
drop(ns_string);
println!("{}", s);
});
}
9 changes: 9 additions & 0 deletions tests/ui/nsstring_as_str_use_after_release.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0505]: cannot move out of `ns_string` because it is borrowed
--> ui/nsstring_as_str_use_after_release.rs:10:14
|
9 | let s = ns_string.as_str(pool);
| ---------------------- borrow of `ns_string` occurs here
10 | drop(ns_string);
| ^^^^^^^^^ move out of `ns_string` occurs here
11 | println!("{}", s);
| - borrow later used here
9 changes: 9 additions & 0 deletions tests/ui/nsstring_as_str_use_outside_pool.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
//! Test that the lifetime of `NSString::as_str` is bound to the pool.

use objc2::rc::autoreleasepool;
use objc2_foundation::NSString;

fn main() {
let ns_string = NSString::new();
let _s = autoreleasepool(|pool| ns_string.as_str(pool));
}
8 changes: 8 additions & 0 deletions tests/ui/nsstring_as_str_use_outside_pool.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
error: lifetime may not live long enough
--> ui/nsstring_as_str_use_outside_pool.rs:8:37
|
8 | let _s = autoreleasepool(|pool| ns_string.as_str(pool));
| ----- ^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
| | |
| | return type of closure is &'2 str
| has type `&'1 AutoreleasePool`
Loading

0 comments on commit ddf483a

Please sign in to comment.