Revision control
Copy as Markdown
Other Tools
#![warn(rust_2018_idioms, single_use_lifetimes)]
use std::{cell::Cell, pin::Pin, thread};
use pin_project::pin_project;
struct D<'a>(&'a Cell<usize>, usize);
impl Drop for D<'_> {
fn drop(&mut self) {
if !thread::panicking() {
let old = self.0.replace(self.1);
assert_eq!(old, self.1 - 1);
}
}
}
#[pin_project(project_replace)]
struct StructPinned<'a> {
#[pin]
f1: D<'a>,
#[pin]
f2: D<'a>,
}
#[pin_project(project_replace)]
struct StructUnpinned<'a> {
f1: D<'a>,
f2: D<'a>,
}
#[pin_project(project_replace)]
struct TuplePinned<'a>(#[pin] D<'a>, #[pin] D<'a>);
#[pin_project(project_replace)]
struct TupleUnpinned<'a>(D<'a>, D<'a>);
#[pin_project(project_replace = EnumProj)]
enum Enum<'a> {
#[allow(dead_code)] // false positive that fixed in Rust 1.38
StructPinned {
#[pin]
f1: D<'a>,
#[pin]
f2: D<'a>,
},
#[allow(dead_code)] // false positive that fixed in Rust 1.38
StructUnpinned {
f1: D<'a>,
f2: D<'a>,
},
TuplePinned(#[pin] D<'a>, #[pin] D<'a>),
TupleUnpinned(D<'a>, D<'a>),
}
#[test]
fn struct_pinned() {
{
let c = Cell::new(0);
let _x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
}
{
let c = Cell::new(0);
let mut x = StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
let y = Pin::new(&mut x);
let _z = y.project_replace(StructPinned { f1: D(&c, 3), f2: D(&c, 4) });
}
}
#[test]
fn struct_unpinned() {
{
let c = Cell::new(0);
let _x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
}
{
let c = Cell::new(0);
let mut x = StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
let y = Pin::new(&mut x);
let _z = y.project_replace(StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) });
}
}
#[test]
fn tuple_pinned() {
{
let c = Cell::new(0);
let _x = TuplePinned(D(&c, 1), D(&c, 2));
}
{
let c = Cell::new(0);
let mut x = TuplePinned(D(&c, 1), D(&c, 2));
let y = Pin::new(&mut x);
let _z = y.project_replace(TuplePinned(D(&c, 3), D(&c, 4)));
}
}
#[test]
fn tuple_unpinned() {
{
let c = Cell::new(0);
let _x = TupleUnpinned(D(&c, 1), D(&c, 2));
}
{
let c = Cell::new(0);
let mut x = TupleUnpinned(D(&c, 1), D(&c, 2));
let y = Pin::new(&mut x);
let _z = y.project_replace(TupleUnpinned(D(&c, 3), D(&c, 4)));
}
}
#[test]
fn enum_struct() {
{
let c = Cell::new(0);
let _x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
}
{
let c = Cell::new(0);
let mut x = Enum::StructPinned { f1: D(&c, 1), f2: D(&c, 2) };
let y = Pin::new(&mut x);
let _z = y.project_replace(Enum::StructPinned { f1: D(&c, 3), f2: D(&c, 4) });
}
{
let c = Cell::new(0);
let _x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
}
{
let c = Cell::new(0);
let mut x = Enum::StructUnpinned { f1: D(&c, 1), f2: D(&c, 2) };
let y = Pin::new(&mut x);
let _z = y.project_replace(Enum::StructUnpinned { f1: D(&c, 3), f2: D(&c, 4) });
}
}
#[test]
fn enum_tuple() {
{
let c = Cell::new(0);
let _x = Enum::TuplePinned(D(&c, 1), D(&c, 2));
}
{
let c = Cell::new(0);
let mut x = Enum::TuplePinned(D(&c, 1), D(&c, 2));
let y = Pin::new(&mut x);
let _z = y.project_replace(Enum::TuplePinned(D(&c, 3), D(&c, 4)));
}
{
let c = Cell::new(0);
let _x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2));
}
{
let c = Cell::new(0);
let mut x = Enum::TupleUnpinned(D(&c, 1), D(&c, 2));
let y = Pin::new(&mut x);
let _z = y.project_replace(Enum::TupleUnpinned(D(&c, 3), D(&c, 4)));
}
}