port compile fail tests to trybuild

closes #127
This commit is contained in:
Jorge Aparicio 2019-12-17 14:11:09 +01:00
parent 06431e7397
commit 906b0679ca
10 changed files with 167 additions and 84 deletions

View File

@ -4,7 +4,7 @@ matrix:
include:
# MSRV: Minimum Supported Rust Version
- env: TARGET=x86_64-unknown-linux-gnu
- env: TARGET=x86_64-unknown-linux-gnu MSRV=1
rust: 1.36.0
if: branch != master

View File

@ -19,8 +19,13 @@ name = "heapless"
repository = "https://github.com/japaric/heapless"
version = "0.5.1"
[[test]]
name = "cfail"
required-features = ["__trybuild"]
[dev-dependencies]
scoped_threadpool = "0.1.8"
trybuild = "1.0.18"
[dependencies]
as-slice = "0.1.0"
@ -31,3 +36,7 @@ hash32 = "0.1.0"
version = "1"
optional = true
default-features = false
[features]
# only for tests
__trybuild = []

View File

@ -8,6 +8,11 @@ main() {
cargo test --target $TARGET --features 'serde'
cargo test --target $TARGET --release --features 'serde'
if [ $MSRV = 1 ]; then
cargo test --features __trybuild --test cfail
fi
if [ $TRAVIS_RUST_VERSION = nightly ]; then
export RUSTFLAGS="-Z sanitizer=thread"
export RUST_TEST_THREADS=1
@ -46,6 +51,10 @@ if [ -z ${TARGET-} ]; then
TARGET=$(rustc -Vv | grep host | cut -d ' ' -f2)
fi
if [ -z ${MSRV-} ]; then
MSRV=1
fi
if [ $TRAVIS_BRANCH != master ]; then
main
fi

View File

@ -1,83 +0,0 @@
//! Compile fail tests
//!
//! # `Send`-ness
//!
//! Collections of `Send`-able things are `Send`
//!
//! ```
//! use heapless::Vec;
//! use heapless::spsc::{Consumer, Queue, Producer};
//! use heapless::consts::*;
//!
//! struct IsSend;
//!
//! unsafe impl Send for IsSend {}
//!
//! fn is_send<T>() where T: Send {}
//!
//! is_send::<Consumer<IsSend, U4>>();
//! is_send::<Producer<IsSend, U4>>();
//! is_send::<Queue<IsSend, U4>>();
//! is_send::<Vec<IsSend, U4>>();
//! ```
//!
//! Collections of non-`Send`-able things are *not* `Send`
//!
//! ``` compile_fail
//! use std::marker::PhantomData;
//! use heapless::ring_buffer::Consumer;
//! use heapless::consts::*;
//!
//! type NotSend = PhantomData<*const ()>;
//!
//! fn is_send<T>() where T: Send {}
//!
//! is_send::<Consumer<NotSend, U4>>();
//! ```
//!
//! ``` compile_fail
//! use std::marker::PhantomData;
//! use heapless::ring_buffer::Producer;
//! use heapless::consts::*;
//!
//! type NotSend = PhantomData<*const ()>;
//!
//! fn is_send<T>() where T: Send {}
//!
//! is_send::<Producer<NotSend, U4>>();
//! ```
//!
//! ``` compile_fail
//! use std::marker::PhantomData;
//! use heapless::spsc::Queue;
//!
//! type NotSend = PhantomData<*const ()>;
//!
//! fn is_send<T>() where T: Send {}
//!
//! is_send::<Queue<NotSend, [NotSend; 4]>>();
//! ```
//!
//! ``` compile_fail
//! use std::marker::PhantomData;
//! use heapless::Vec;
//!
//! type NotSend = PhantomData<*const ()>;
//!
//! fn is_send<T>() where T: Send {}
//!
//! is_send::<Vec<NotSend, [NotSend; 4]>>();
//! ```
//!
//! # Freeze
//!
//! Splitting a `Queue` should invalidate the original reference.
//!
//! ``` compile_fail
//! use heapless::spsc::Queue;
//!
//! let mut rb: Queue<u8, [u8; 4]> = Queue::new();
//!
//! let (p, c) = rb.split();
//! rb.enqueue(0).unwrap();
//! ```

7
tests/cfail.rs Normal file
View File

@ -0,0 +1,7 @@
use trybuild::TestCases;
#[test]
fn ui() {
let t = TestCases::new();
t.compile_fail("ui/*.rs");
}

25
tests/cpass.rs Normal file
View File

@ -0,0 +1,25 @@
//! Collections of `Send`-able things are `Send`
use heapless::{
consts,
spsc::{Consumer, Producer, Queue},
Vec,
};
#[test]
fn send() {
struct IsSend;
unsafe impl Send for IsSend {}
fn is_send<T>()
where
T: Send,
{
}
is_send::<Consumer<IsSend, consts::U4>>();
is_send::<Producer<IsSend, consts::U4>>();
is_send::<Queue<IsSend, consts::U4>>();
is_send::<Vec<IsSend, consts::U4>>();
}

9
ui/freeze.rs Normal file
View File

@ -0,0 +1,9 @@
use heapless::{consts, spsc::Queue};
fn main() {
let mut q: Queue<u8, consts::U4> = Queue::new();
let (_p, mut _c) = q.split();
q.enqueue(0).unwrap();
_c.dequeue();
}

9
ui/freeze.stderr Normal file
View File

@ -0,0 +1,9 @@
error[E0499]: cannot borrow `q` as mutable more than once at a time
--> $DIR/freeze.rs:7:5
|
6 | let (_p, mut _c) = q.split();
| - first mutable borrow occurs here
7 | q.enqueue(0).unwrap();
| ^ second mutable borrow occurs here
8 | _c.dequeue();
| -- first borrow later used here

23
ui/not-send.rs Normal file
View File

@ -0,0 +1,23 @@
//! Collections of non-`Send`-able things are *not* `Send`
use core::marker::PhantomData;
use heapless::{
consts,
spsc::{Consumer, Producer, Queue},
};
type NotSend = PhantomData<*const ()>;
fn is_send<T>()
where
T: Send,
{
}
fn main() {
is_send::<Consumer<NotSend, consts::U4>>();
is_send::<Producer<NotSend, consts::U4>>();
is_send::<Queue<NotSend, consts::U4>>();
is_send::<Vec<NotSend, consts::U4>>();
}

75
ui/not-send.stderr Normal file
View File

@ -0,0 +1,75 @@
error[E0277]: `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:19:5
|
12 | fn is_send<T>()
| -------
13 | where
14 | T: Send,
| ---- required by this bound in `is_send`
...
19 | is_send::<Consumer<NotSend, consts::U4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
|
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
= note: required because of the requirements on the impl of `std::marker::Send` for `heapless::spsc::split::Consumer<'_, std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
error[E0277]: `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:20:5
|
12 | fn is_send<T>()
| -------
13 | where
14 | T: Send,
| ---- required by this bound in `is_send`
...
20 | is_send::<Producer<NotSend, consts::U4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
|
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
= note: required because of the requirements on the impl of `std::marker::Send` for `heapless::spsc::split::Producer<'_, std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
error[E0277]: `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:21:5
|
12 | fn is_send<T>()
| -------
13 | where
14 | T: Send,
| ---- required by this bound in `is_send`
...
21 | is_send::<Queue<NotSend, consts::U4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
|
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
= note: required because of the requirements on the impl of `std::marker::Send` for `generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
= note: required because it appears within the type `std::mem::ManuallyDrop<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `std::mem::MaybeUninit<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `heapless::i::Queue<generic_array::GenericArray<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>>`
= note: required because it appears within the type `heapless::spsc::Queue<std::marker::PhantomData<*const ()>, typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UInt<typenum::uint::UTerm, typenum::bit::B1>, typenum::bit::B0>, typenum::bit::B0>>`
error[E0107]: wrong number of type arguments: expected 1, found 2
--> $DIR/not-send.rs:22:28
|
22 | is_send::<Vec<NotSend, consts::U4>>();
| ^^^^^^^^^^ unexpected type argument
error[E0277]: `*const ()` cannot be sent between threads safely
--> $DIR/not-send.rs:22:5
|
12 | fn is_send<T>()
| -------
13 | where
14 | T: Send,
| ---- required by this bound in `is_send`
...
22 | is_send::<Vec<NotSend, consts::U4>>();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*const ()` cannot be sent between threads safely
|
= help: within `std::marker::PhantomData<*const ()>`, the trait `std::marker::Send` is not implemented for `*const ()`
= note: required because it appears within the type `std::marker::PhantomData<*const ()>`
= note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<std::marker::PhantomData<*const ()>>`
= note: required because it appears within the type `alloc::raw_vec::RawVec<std::marker::PhantomData<*const ()>>`
= note: required because it appears within the type `std::vec::Vec<std::marker::PhantomData<*const ()>>`