blob: e25775810f1da3b77375138603fcd67d3b54a1c2 [file] [log] [blame]
#![warn(rust_2018_idioms, single_use_lifetimes)]
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
#[test]
fn safe_project() {
#[pin_project(PinnedDrop)]
pub struct Struct<'a> {
was_dropped: &'a mut bool,
#[pin]
field: u8,
}
#[pinned_drop]
impl PinnedDrop for Struct<'_> {
fn drop(self: Pin<&mut Self>) {
**self.project().was_dropped = true;
}
}
let mut was_dropped = false;
drop(Struct { was_dropped: &mut was_dropped, field: 42 });
assert!(was_dropped);
}
#[test]
fn self_argument_in_macro() {
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
#[pin_project(PinnedDrop)]
struct Struct {
x: (),
}
#[pinned_drop]
impl PinnedDrop for Struct {
fn drop(self: Pin<&mut Self>) {
let _: Vec<_> = vec![self.x];
}
}
}
#[test]
fn self_in_macro_containing_fn() {
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
macro_rules! mac {
($($tt:tt)*) => {
$($tt)*
};
}
#[pin_project(PinnedDrop)]
pub struct Struct {
_x: (),
}
#[pinned_drop]
impl PinnedDrop for Struct {
fn drop(self: Pin<&mut Self>) {
let _ = mac!({
impl Struct {
pub fn _f(self) -> Self {
self
}
}
});
}
}
}
#[test]
fn self_call() {
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
#[pin_project(PinnedDrop)]
pub struct Struct<T> {
_x: T,
}
trait Trait {
fn self_ref(&self) {}
fn self_pin_ref(self: Pin<&Self>) {}
fn self_mut(&mut self) {}
fn self_pin_mut(self: Pin<&mut Self>) {}
fn assoc_fn(_this: Pin<&mut Self>) {}
}
impl<T> Trait for Struct<T> {}
#[pinned_drop]
impl<T> PinnedDrop for Struct<T> {
fn drop(mut self: Pin<&mut Self>) {
self.self_ref();
self.as_ref().self_pin_ref();
self.self_mut();
self.as_mut().self_pin_mut();
Self::assoc_fn(self.as_mut());
<Self>::assoc_fn(self.as_mut());
}
}
}
#[test]
fn self_struct() {
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
#[pin_project(PinnedDrop)]
pub struct Struct {
pub x: (),
}
#[pinned_drop]
impl PinnedDrop for Struct {
#[allow(irrefutable_let_patterns)]
#[allow(clippy::match_single_binding)]
fn drop(mut self: Pin<&mut Self>) {
// expr
let _: Self = Self { x: () };
// pat
match *self {
Self { x: _ } => {}
}
if let Self { x: _ } = *self {}
let Self { x: _ } = *self;
}
}
#[pin_project(PinnedDrop)]
pub struct TupleStruct(());
#[pinned_drop]
impl PinnedDrop for TupleStruct {
#[allow(irrefutable_let_patterns)]
fn drop(mut self: Pin<&mut Self>) {
// expr
let _: Self = Self(());
// pat
match *self {
Self(_) => {}
}
if let Self(_) = *self {}
let Self(_) = *self;
}
}
}
#[rustversion::since(1.37)] // type_alias_enum_variants requires Rust 1.37
#[test]
fn self_enum() {
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
#[pin_project(PinnedDrop)]
pub enum Enum {
Struct { x: () },
Tuple(()),
}
#[pinned_drop]
impl PinnedDrop for Enum {
fn drop(mut self: Pin<&mut Self>) {
// expr
let _: Self = Self::Struct { x: () };
let _: Self = Self::Tuple(());
// pat
match *self {
Self::Struct { x: _ } => {}
Self::Tuple(_) => {}
}
if let Self::Struct { x: _ } = *self {}
if let Self::Tuple(_) = *self {}
}
}
}
// See also `ui/pinned_drop/self.rs`.
#[rustversion::since(1.40)] // https://github.com/rust-lang/rust/pull/64690
#[test]
fn self_in_macro_def() {
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
#[pin_project(PinnedDrop)]
pub struct Struct {
_x: (),
}
#[pinned_drop]
impl PinnedDrop for Struct {
fn drop(self: Pin<&mut Self>) {
macro_rules! mac {
() => {{
let _ = self;
}};
}
mac!();
}
}
}
#[test]
fn self_inside_macro() {
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
macro_rules! mac {
($($tt:tt)*) => {
$($tt)*
};
}
#[pin_project(PinnedDrop)]
pub struct Struct<T: Send>
where
mac!(Self): Send,
{
_x: T,
}
impl<T: Send> Struct<T> {
const ASSOCIATED1: &'static str = "1";
fn associated1() {}
}
trait Trait {
type Associated2;
const ASSOCIATED2: &'static str;
fn associated2();
}
impl<T: Send> Trait for Struct<T> {
type Associated2 = ();
const ASSOCIATED2: &'static str = "2";
fn associated2() {}
}
#[pinned_drop]
impl<T: Send> PinnedDrop for Struct<T>
where
mac!(Self): Send,
{
#[allow(path_statements)]
#[allow(clippy::no_effect)]
fn drop(self: Pin<&mut Self>) {
// inherent items
mac!(Self::ASSOCIATED1;);
mac!(<Self>::ASSOCIATED1;);
mac!(Self::associated1(););
mac!(<Self>::associated1(););
// trait items
mac!(let _: <Self as Trait>::Associated2;);
mac!(Self::ASSOCIATED2;);
mac!(<Self>::ASSOCIATED2;);
mac!(<Self as Trait>::ASSOCIATED2;);
mac!(Self::associated2(););
mac!(<Self>::associated2(););
mac!(<Self as Trait>::associated2(););
}
}
}
#[test]
fn inside_macro() {
use pin_project::{pin_project, pinned_drop};
use std::pin::Pin;
#[pin_project(PinnedDrop)]
struct Struct(());
macro_rules! mac {
($expr:expr) => {
#[pinned_drop]
impl PinnedDrop for Struct {
#[allow(clippy::no_effect)]
fn drop(self: Pin<&mut Self>) {
$expr;
}
}
};
}
mac!(1);
}