You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
265 lines
5.7 KiB
265 lines
5.7 KiB
#![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>) {
|
|
let _ = 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 = ();
|
|
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);
|
|
}
|