| #![warn(rust_2018_idioms, single_use_lifetimes)] |
| #![allow(dead_code)] |
| |
| // Refs: https://doc.rust-lang.org/reference/attributes.html |
| |
| #[macro_use] |
| mod auxiliary; |
| |
| use std::{marker::PhantomPinned, pin::Pin}; |
| |
| use pin_project::pin_project; |
| |
| struct Always; |
| |
| // Use this type to check that `cfg(any())` is working properly. |
| struct Never(PhantomPinned); |
| |
| #[test] |
| fn cfg() { |
| // structs |
| |
| #[pin_project(project_replace)] |
| struct SameName { |
| #[cfg(not(any()))] |
| #[pin] |
| inner: Always, |
| #[cfg(any())] |
| #[pin] |
| inner: Never, |
| } |
| |
| assert_unpin!(SameName); |
| |
| let _ = SameName { inner: Always }; |
| |
| #[pin_project(project_replace)] |
| struct DifferentName { |
| #[cfg(not(any()))] |
| #[pin] |
| a: Always, |
| #[cfg(any())] |
| #[pin] |
| n: Never, |
| } |
| |
| assert_unpin!(DifferentName); |
| |
| let _ = DifferentName { a: Always }; |
| |
| #[pin_project(project_replace)] |
| struct TupleStruct( |
| #[cfg(not(any()))] |
| #[pin] |
| Always, |
| #[cfg(any())] |
| #[pin] |
| Never, |
| ); |
| |
| assert_unpin!(TupleStruct); |
| |
| let _ = TupleStruct(Always); |
| |
| // enums |
| |
| #[pin_project( |
| project = VariantProj, |
| project_ref = VariantProjRef, |
| project_replace = VariantProjOwn, |
| )] |
| enum Variant { |
| #[cfg(not(any()))] |
| Inner(#[pin] Always), |
| #[cfg(any())] |
| Inner(#[pin] Never), |
| |
| #[cfg(not(any()))] |
| A(#[pin] Always), |
| #[cfg(any())] |
| N(#[pin] Never), |
| } |
| |
| assert_unpin!(Variant); |
| |
| let _ = Variant::Inner(Always); |
| let _ = Variant::A(Always); |
| |
| #[pin_project( |
| project = FieldProj, |
| project_ref = FieldProjRef, |
| project_replace = FieldProjOwn, |
| )] |
| enum Field { |
| SameName { |
| #[cfg(not(any()))] |
| #[pin] |
| inner: Always, |
| #[cfg(any())] |
| #[pin] |
| inner: Never, |
| }, |
| DifferentName { |
| #[cfg(not(any()))] |
| #[pin] |
| a: Always, |
| #[cfg(any())] |
| #[pin] |
| n: Never, |
| }, |
| TupleVariant( |
| #[cfg(not(any()))] |
| #[pin] |
| Always, |
| #[cfg(any())] |
| #[pin] |
| Never, |
| ), |
| } |
| |
| assert_unpin!(Field); |
| |
| let _ = Field::SameName { inner: Always }; |
| let _ = Field::DifferentName { a: Always }; |
| let _ = Field::TupleVariant(Always); |
| } |
| |
| #[test] |
| fn cfg_attr() { |
| #[pin_project(project_replace)] |
| struct SameCfg { |
| #[cfg(not(any()))] |
| #[cfg_attr(not(any()), pin)] |
| inner: Always, |
| #[cfg(any())] |
| #[cfg_attr(any(), pin)] |
| inner: Never, |
| } |
| |
| assert_unpin!(SameCfg); |
| |
| let mut x = SameCfg { inner: Always }; |
| let x = Pin::new(&mut x).project(); |
| let _: Pin<&mut Always> = x.inner; |
| |
| #[pin_project(project_replace)] |
| struct DifferentCfg { |
| #[cfg(not(any()))] |
| #[cfg_attr(any(), pin)] |
| inner: Always, |
| #[cfg(any())] |
| #[cfg_attr(not(any()), pin)] |
| inner: Never, |
| } |
| |
| assert_unpin!(DifferentCfg); |
| |
| let mut x = DifferentCfg { inner: Always }; |
| let x = Pin::new(&mut x).project(); |
| let _: &mut Always = x.inner; |
| |
| #[cfg_attr(not(any()), pin_project)] |
| struct Foo<T> { |
| #[cfg_attr(not(any()), pin)] |
| inner: T, |
| } |
| |
| assert_unpin!(Foo<()>); |
| assert_not_unpin!(Foo<PhantomPinned>); |
| |
| let mut x = Foo { inner: 0_u8 }; |
| let x = Pin::new(&mut x).project(); |
| let _: Pin<&mut u8> = x.inner; |
| } |
| |
| #[test] |
| fn cfg_attr_any_packed() { |
| // Since `cfg(any())` can never be true, it is okay for this to pass. |
| #[pin_project(project_replace)] |
| #[cfg_attr(any(), repr(packed))] |
| struct Struct { |
| #[pin] |
| f: u32, |
| } |
| } |