Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hide all generated items except for projected types from calling code #192

Merged
merged 1 commit into from
Apr 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,10 @@ jobs:
- name: cargo test
run: |
cargo test --all
- name: cargo test --cfg pin_project_show_unpin_struct
- name: cargo test -- --ignored
if: matrix.rust == 'nightly'
env:
RUSTFLAGS: -Dwarnings --cfg pin_project_show_unpin_struct
run: |
cargo test --all --all-features -- -Zunstable-options --include-ignored
cargo test --all -- --ignored
# Refs: https://github.com/rust-lang/cargo/issues/5657
- name: cargo check -Zminimal-versions
if: matrix.rust == 'nightly'
Expand Down
4 changes: 2 additions & 2 deletions compiletest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
# . ./compiletest.sh
# ```

TRYBUILD=overwrite RUSTFLAGS='--cfg pin_project_show_unpin_struct' cargo +nightly test -p pin-project --all-features --test compiletest -- --ignored
# RUSTFLAGS='--cfg pin_project_show_unpin_struct' cargo +nightly test -p pin-project --all-features --test compiletest -- --ignored
TRYBUILD=overwrite cargo +nightly test -p pin-project --all-features --test compiletest -- --ignored
# cargo +nightly test -p pin-project --all-features --test compiletest -- --ignored
81 changes: 47 additions & 34 deletions examples/enum-default-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,62 +25,75 @@ enum Enum<T, U> {

#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
#[allow(dead_code)] // This lint warns unused fields/variants.
enum __EnumProjection<'pin, T, U> {
enum __EnumProjection<'pin, T, U>
where
Enum<T, U>: 'pin,
{
Pinned(::core::pin::Pin<&'pin mut (T)>),
Unpinned(&'pin mut (U)),
}

#[allow(dead_code)] // This lint warns unused fields/variants.
enum __EnumProjectionRef<'pin, T, U> {
enum __EnumProjectionRef<'pin, T, U>
where
Enum<T, U>: 'pin,
{
Pinned(::core::pin::Pin<&'pin (T)>),
Unpinned(&'pin (U)),
}

impl<T, U> Enum<T, U> {
fn project<'pin>(self: ::core::pin::Pin<&'pin mut Self>) -> __EnumProjection<'pin, T, U> {
unsafe {
match self.get_unchecked_mut() {
Enum::Pinned(_0) => __EnumProjection::Pinned(::core::pin::Pin::new_unchecked(_0)),
Enum::Unpinned(_0) => __EnumProjection::Unpinned(_0),
#[allow(non_upper_case_globals)]
const __SCOPE_Enum: () = {
impl<T, U> Enum<T, U> {
fn project<'pin>(self: ::core::pin::Pin<&'pin mut Self>) -> __EnumProjection<'pin, T, U> {
unsafe {
match self.get_unchecked_mut() {
Enum::Pinned(_0) => {
__EnumProjection::Pinned(::core::pin::Pin::new_unchecked(_0))
}
Enum::Unpinned(_0) => __EnumProjection::Unpinned(_0),
}
}
}
}
fn project_ref<'pin>(self: ::core::pin::Pin<&'pin Self>) -> __EnumProjectionRef<'pin, T, U> {
unsafe {
match self.get_ref() {
Enum::Pinned(_0) => {
__EnumProjectionRef::Pinned(::core::pin::Pin::new_unchecked(_0))
fn project_ref<'pin>(
self: ::core::pin::Pin<&'pin Self>,
) -> __EnumProjectionRef<'pin, T, U> {
unsafe {
match self.get_ref() {
Enum::Pinned(_0) => {
__EnumProjectionRef::Pinned(::core::pin::Pin::new_unchecked(_0))
}
Enum::Unpinned(_0) => __EnumProjectionRef::Unpinned(_0),
}
Enum::Unpinned(_0) => __EnumProjectionRef::Unpinned(_0),
}
}
}
}

// Automatically create the appropriate conditional `Unpin` implementation.
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53.
// for details.
#[allow(non_snake_case)]
fn __unpin_scope_Enum() {
// Automatically create the appropriate conditional `Unpin` implementation.
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53.
// for details.
struct __Enum<'pin, T, U> {
__pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T, U)>,
__field0: T,
}
impl<'pin, T, U> ::core::marker::Unpin for Enum<T, U> where __Enum<'pin, T, U>: ::core::marker::Unpin
{}
}

// Ensure that enum does not implement `Drop`.
//
// See ./struct-default-expanded.rs for details.
trait EnumMustNotImplDrop {}
#[allow(clippy::drop_bounds)]
impl<T: ::core::ops::Drop> EnumMustNotImplDrop for T {}
#[allow(single_use_lifetimes)]
impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
// Ensure that enum does not implement `Drop`.
//
// See ./struct-default-expanded.rs for details.
trait EnumMustNotImplDrop {}
#[allow(clippy::drop_bounds)]
impl<T: ::core::ops::Drop> EnumMustNotImplDrop for T {}
#[allow(single_use_lifetimes)]
impl<T, U> EnumMustNotImplDrop for Enum<T, U> {}
#[allow(single_use_lifetimes)]
impl<T, U> ::pin_project::__private::PinnedDrop for Enum<T, U> {
unsafe fn drop(self: ::core::pin::Pin<&mut Self>) {}
}

// We don't need to check for '#[repr(packed)]',
// since it does not apply to enums.
// We don't need to check for `#[repr(packed)]`,
// since it does not apply to enums.
};

fn main() {}
138 changes: 71 additions & 67 deletions examples/pinned_drop-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,79 +34,84 @@ pub struct Foo<'a, T> {

#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
#[allow(dead_code)] // This lint warns unused fields/variants.
pub(crate) struct __FooProjection<'pin, 'a, T> {
pub(crate) struct __FooProjection<'pin, 'a, T>
where
Foo<'a, T>: 'pin,
{
was_dropped: &'pin mut (&'a mut bool),
field: ::core::pin::Pin<&'pin mut (T)>,
}

#[allow(dead_code)] // This lint warns unused fields/variants.
pub(crate) struct __FooProjectionRef<'pin, 'a, T> {
pub(crate) struct __FooProjectionRef<'pin, 'a, T>
where
Foo<'a, T>: 'pin,
{
was_dropped: &'pin (&'a mut bool),
field: ::core::pin::Pin<&'pin (T)>,
}

impl<'a, T> Foo<'a, T> {
pub(crate) fn project<'pin>(
self: ::core::pin::Pin<&'pin mut Self>,
) -> __FooProjection<'pin, 'a, T> {
unsafe {
let Foo { was_dropped, field } = self.get_unchecked_mut();
__FooProjection { was_dropped, field: ::core::pin::Pin::new_unchecked(field) }
#[allow(non_upper_case_globals)]
const __SCOPE_Foo: () = {
impl<'a, T> Foo<'a, T> {
pub(crate) fn project<'pin>(
self: ::core::pin::Pin<&'pin mut Self>,
) -> __FooProjection<'pin, 'a, T> {
unsafe {
let Foo { was_dropped, field } = self.get_unchecked_mut();
__FooProjection { was_dropped, field: ::core::pin::Pin::new_unchecked(field) }
}
}
}
pub(crate) fn project_ref<'pin>(
self: ::core::pin::Pin<&'pin Self>,
) -> __FooProjectionRef<'pin, 'a, T> {
unsafe {
let Foo { was_dropped, field } = self.get_ref();
__FooProjectionRef { was_dropped, field: ::core::pin::Pin::new_unchecked(field) }
pub(crate) fn project_ref<'pin>(
self: ::core::pin::Pin<&'pin Self>,
) -> __FooProjectionRef<'pin, 'a, T> {
unsafe {
let Foo { was_dropped, field } = self.get_ref();
__FooProjectionRef { was_dropped, field: ::core::pin::Pin::new_unchecked(field) }
}
}
}
}

#[allow(single_use_lifetimes)]
impl<'a, T> ::core::ops::Drop for Foo<'a, T> {
fn drop(&mut self) {
// Safety - we're in 'drop', so we know that 'self' will
// never move again.
let pinned_self = unsafe { ::core::pin::Pin::new_unchecked(self) };
// We call `pinned_drop` only once. Since `PinnedDrop::drop`
// is an unsafe function and a private API, it is never called again in safe
// code *unless the user uses a maliciously crafted macro*.
unsafe {
::pin_project::__private::PinnedDrop::drop(pinned_self);
#[allow(single_use_lifetimes)]
impl<'a, T> ::core::ops::Drop for Foo<'a, T> {
fn drop(&mut self) {
// Safety - we're in 'drop', so we know that 'self' will
// never move again.
let pinned_self = unsafe { ::core::pin::Pin::new_unchecked(self) };
// We call `pinned_drop` only once. Since `PinnedDrop::drop`
// is an unsafe method and a private API, it is never called again in safe
// code *unless the user uses a maliciously crafted macro*.
unsafe {
::pin_project::__private::PinnedDrop::drop(pinned_self);
}
}
}
}

// It is safe to implement PinnedDrop::drop, but it is not safe to call it.
// This is because destructors can be called multiple times (double dropping
// is unsound: rust-lang/rust#62360).
//
// Ideally, it would be desirable to be able to prohibit manual calls in the
// same way as Drop::drop, but the library cannot. So, by using macros and
// replacing them with private traits, we prevent users from calling
// PinnedDrop::drop.
//
// Users can implement `Drop` safely using `#[pinned_drop]`.
// **Do not call or implement this trait directly.**
impl<T> ::pin_project::__private::PinnedDrop for Foo<'_, T> {
// Since calling it twice on the same object would be UB,
// this method is unsafe.
unsafe fn drop(self: Pin<&mut Self>) {
fn __drop_inner<T>(__self: Pin<&mut Foo<'_, T>>) {
**__self.project().was_dropped = true;
// It is safe to implement PinnedDrop::drop, but it is not safe to call it.
// This is because destructors can be called multiple times (double dropping
// is unsound: rust-lang/rust#62360).
//
// Ideally, it would be desirable to be able to prohibit manual calls in the
// same way as Drop::drop, but the library cannot. So, by using macros and
// replacing them with private traits, we prevent users from calling
// PinnedDrop::drop.
//
// Users can implement `Drop` safely using `#[pinned_drop]`.
// **Do not call or implement this trait directly.**
impl<T> ::pin_project::__private::PinnedDrop for Foo<'_, T> {
// Since calling it twice on the same object would be UB,
// this method is unsafe.
unsafe fn drop(self: Pin<&mut Self>) {
fn __drop_inner<T>(__self: Pin<&mut Foo<'_, T>>) {
**__self.project().was_dropped = true;
}
__drop_inner(self);
}
__drop_inner(self);
}
}

// Automatically create the appropriate conditional `Unpin` implementation.
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53.
// for details.
#[allow(non_snake_case)]
fn __unpin_scope_Foo() {
// Automatically create the appropriate conditional `Unpin` implementation.
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/53.
// for details.
pub struct __Foo<'pin, 'a, T> {
__pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T)>,
__field0: T,
Expand All @@ -116,18 +121,17 @@ fn __unpin_scope_Foo() {
__Foo<'pin, 'a, T>: ::core::marker::Unpin
{
}
}

// Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
// for details.
#[allow(single_use_lifetimes)]
#[allow(non_snake_case)]
#[deny(safe_packed_borrows)]
fn __pin_project_assert_not_repr_packed_Foo<'a, T>(val: &Foo<'a, T>) {
&val.was_dropped;
&val.field;
}
// Ensure that it's impossible to use pin projections on a #[repr(packed)] struct.
//
// See ./struct-default-expanded.rs and https://github.com/taiki-e/pin-project/pull/34
// for details.
#[allow(single_use_lifetimes)]
#[deny(safe_packed_borrows)]
fn __assert_not_repr_packed<'a, T>(val: &Foo<'a, T>) {
&val.was_dropped;
&val.field;
}
};

fn main() {}
Loading