#![warn(rust_2018_idioms, single_use_lifetimes)]
use std::pin::Pin;
use pin_project::{pin_project, pinned_drop};
#[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_call() {
#[pin_project(PinnedDrop)]
pub struct S<T>(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 S<T> {}
#[pinned_drop]
impl<T> PinnedDrop
for S<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_ty() {
#[pin_project(PinnedDrop)]
pub struct Struct {
pub f: (),
}
#[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 { f: () };
// pat
match *
self {
Self { f: () } => {}
}
if let Self { f: () } = *
self {}
let Self { f: () } = *
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;
}
}
#[pin_project(PinnedDrop, project = EnumProj, project_ref = EnumProjRef)]
pub enum Enum {
Struct { f: () },
Tuple(()),
Unit,
}
#[pinned_drop]
impl PinnedDrop
for Enum {
fn drop(
mut self: Pin<&
mut Self>) {
// expr
let _:
Self =
Self::
Struct { f: () };
let _:
Self =
Self::Tuple(());
let _:
Self =
Self::Unit;
// pat
match *
self {
Self::
Struct { f: () } => {}
Self::Tuple(_) => {}
Self::Unit => {}
}
if let Self::
Struct { f: () } = *
self {}
if let Self::Tuple(_) = *
self {}
if let Self::Unit = *
self {}
}
}
}
#[test]
fn self_inside_macro_containing_fn() {
macro_rules! mac {
($($tt:tt)*) => {
$($tt)*
};
}
#[pin_project(PinnedDrop)]
pub struct S(());
#[pinned_drop]
impl PinnedDrop
for S {
fn drop(
self: Pin<&
mut Self>) {
mac!({
impl S {
pub fn _f(
self) ->
Self {
self
}
}
});
}
}
}
// See also `ui/pinned_drop/self.rs`.
#[rustversion::since(
1.
40)]
// https://github.com/rust-lang/rust/pull/64690
#[test]
fn self_inside_macro_def() {
#[pin_project(PinnedDrop)]
pub struct S(());
#[pinned_drop]
impl PinnedDrop
for S {
fn drop(
self: Pin<&
mut Self>) {
macro_rules! mac {
() => {{
let _ =
self;
let _ =
Self(());
}};
}
mac!();
}
}
}
#[test]
fn self_arg_inside_macro_call() {
#[pin_project(PinnedDrop)]
struct Struct {
f: (),
}
#[pinned_drop]
impl PinnedDrop
for Struct {
fn drop(
self: Pin<&
mut Self>) {
let _: Vec<_> = vec![
self.f];
}
}
}
#[test]
fn self_ty_inside_macro_call() {
macro_rules! mac {
($($tt:tt)*) => {
$($tt)*
};
}
#[pin_project(PinnedDrop)]
pub struct Struct<T: Send>
where
mac!(
Self): Send,
{
_f: T,
}
impl<T: Send>
Struct<T> {
const ASSOC1: usize =
1;
fn assoc1() {}
}
trait Trait {
type Assoc2;
const ASSOC2: usize;
fn assoc2();
}
impl<T: Send>
Trait for Struct<T> {
type Assoc2 = u8;
const ASSOC2: usize =
2;
fn assoc2() {}
}
#[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::ASSOC1;);
mac!(<
Self>::ASSOC1;);
mac!(
Self::assoc1(););
mac!(<
Self>::assoc1(););
// trait items
mac!(
let _: <
Self as Trait>::Assoc2;);
mac!(
Self::ASSOC2;);
mac!(<
Self>::ASSOC2;);
mac!(<
Self as Trait>::ASSOC2;);
mac!(
Self::assoc2(););
mac!(<
Self>::assoc2(););
mac!(<
Self as Trait>::assoc2(););
}
}
}
#[test]
fn inside_macro() {
#[pin_project(PinnedDrop)]
struct S(());
macro_rules! mac {
($expr:expr) => {
#[pinned_drop]
impl PinnedDrop
for S {
fn drop(
self: Pin<&
mut Self>) {
let _ = $expr;
}
}
};
}
mac!(
1);
}
pub mod self_path {
use super::*;
#[pin_project(PinnedDrop)]
pub struct S<T: Unpin>(T);
fn f() {}
#[pinned_drop]
impl<T: Unpin> PinnedDrop
for self::S<T> {
fn drop(
mut self: Pin<&
mut Self>) {
self::f();
let _:
self::S<()> =
self::S(());
let _:
self::S<Pin<&
mut Self>> =
self::S(
self.as_mut());
let self::S(()) =
self::S(());
let self::S(&
mut Self(_)) =
self::S(&
mut *self);
}
}
}