diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d18e3605..0e60959f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -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' diff --git a/compiletest.sh b/compiletest.sh index 21351a50..9af5a5fc 100644 --- a/compiletest.sh +++ b/compiletest.sh @@ -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 diff --git a/examples/enum-default-expanded.rs b/examples/enum-default-expanded.rs index 568f9b2c..fcf7f2e7 100644 --- a/examples/enum-default-expanded.rs +++ b/examples/enum-default-expanded.rs @@ -25,62 +25,75 @@ enum Enum { #[allow(clippy::mut_mut)] // This lint warns `&mut &mut `. #[allow(dead_code)] // This lint warns unused fields/variants. -enum __EnumProjection<'pin, T, U> { +enum __EnumProjection<'pin, T, U> +where + Enum: '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: 'pin, +{ Pinned(::core::pin::Pin<&'pin (T)>), Unpinned(&'pin (U)), } -impl Enum { - 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 Enum { + 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 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 EnumMustNotImplDrop for T {} -#[allow(single_use_lifetimes)] -impl EnumMustNotImplDrop for Enum {} + // Ensure that enum does not implement `Drop`. + // + // See ./struct-default-expanded.rs for details. + trait EnumMustNotImplDrop {} + #[allow(clippy::drop_bounds)] + impl EnumMustNotImplDrop for T {} + #[allow(single_use_lifetimes)] + impl EnumMustNotImplDrop for Enum {} + #[allow(single_use_lifetimes)] + impl ::pin_project::__private::PinnedDrop for Enum { + 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() {} diff --git a/examples/pinned_drop-expanded.rs b/examples/pinned_drop-expanded.rs index d96dd98e..4f72d98e 100644 --- a/examples/pinned_drop-expanded.rs +++ b/examples/pinned_drop-expanded.rs @@ -34,79 +34,84 @@ pub struct Foo<'a, T> { #[allow(clippy::mut_mut)] // This lint warns `&mut &mut `. #[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 ::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(__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 ::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(__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, @@ -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() {} diff --git a/examples/struct-default-expanded.rs b/examples/struct-default-expanded.rs index ec454b79..4469c842 100644 --- a/examples/struct-default-expanded.rs +++ b/examples/struct-default-expanded.rs @@ -27,58 +27,67 @@ struct Struct { #[allow(clippy::mut_mut)] // This lint warns `&mut &mut `. #[allow(dead_code)] // This lint warns unused fields/variants. -struct __StructProjection<'pin, T, U> { +struct __StructProjection<'pin, T, U> +where + Struct: 'pin, +{ pinned: ::core::pin::Pin<&'pin mut (T)>, unpinned: &'pin mut (U), } #[allow(dead_code)] // This lint warns unused fields/variants. -struct __StructProjectionRef<'pin, T, U> { +struct __StructProjectionRef<'pin, T, U> +where + Struct: 'pin, +{ pinned: ::core::pin::Pin<&'pin (T)>, unpinned: &'pin (U), } -impl Struct { - fn project<'pin>(self: ::core::pin::Pin<&'pin mut Self>) -> __StructProjection<'pin, T, U> { - unsafe { - let Struct { pinned, unpinned } = self.get_unchecked_mut(); - __StructProjection { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned } +#[allow(non_upper_case_globals)] +const __SCOPE_Struct: () = { + impl Struct { + fn project<'pin>(self: ::core::pin::Pin<&'pin mut Self>) -> __StructProjection<'pin, T, U> { + unsafe { + let Struct { pinned, unpinned } = self.get_unchecked_mut(); + __StructProjection { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned } + } } - } - fn project_ref<'pin>(self: ::core::pin::Pin<&'pin Self>) -> __StructProjectionRef<'pin, T, U> { - unsafe { - let Struct { pinned, unpinned } = self.get_ref(); - __StructProjectionRef { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned } + fn project_ref<'pin>( + self: ::core::pin::Pin<&'pin Self>, + ) -> __StructProjectionRef<'pin, T, U> { + unsafe { + let Struct { pinned, unpinned } = self.get_ref(); + __StructProjectionRef { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned } + } } } -} -// Automatically create the appropriate conditional `Unpin` implementation. -// -// Basically this is equivalent to the following code: -// ```rust -// impl Unpin for Struct where T: Unpin {} -// ``` -// -// However, if struct is public and there is a private type field, -// this would cause an E0446 (private type in public interface). -// -// When RFC 2145 is implemented (rust-lang/rust#48054), -// this will become a lint, rather then a hard error. -// -// As a workaround for this, we generate a new struct, containing all of the pinned -// fields from our #[pin_project] type. This struct is declared within -// a function, which makes it impossible to be named by user code. -// This guarantees that it will use the default auto-trait impl for Unpin - -// that is, it will implement Unpin iff all of its fields implement Unpin. -// This type can be safely declared as 'public', satisfying the privacy -// checker without actually allowing user code to access it. -// -// This allows users to apply the #[pin_project] attribute to types -// regardless of the privacy of the types of their fields. -// -// See also https://github.com/taiki-e/pin-project/pull/53. -#[allow(non_snake_case)] -fn __unpin_scope_Struct() { + // Automatically create the appropriate conditional `Unpin` implementation. + // + // Basically this is equivalent to the following code: + // + // ```rust + // impl Unpin for Struct where T: Unpin {} + // ``` + // + // However, if struct is public and there is a private type field, + // this would cause an E0446 (private type in public interface). + // + // When RFC 2145 is implemented (rust-lang/rust#48054), + // this will become a lint, rather then a hard error. + // + // As a workaround for this, we generate a new struct, containing all of the pinned + // fields from our #[pin_project] type. This struct is declared within + // a function, which makes it impossible to be named by user code. + // This guarantees that it will use the default auto-trait impl for Unpin - + // that is, it will implement Unpin iff all of its fields implement Unpin. + // This type can be safely declared as 'public', satisfying the privacy + // checker without actually allowing user code to access it. + // + // This allows users to apply the #[pin_project] attribute to types + // regardless of the privacy of the types of their fields. + // + // See also https://github.com/taiki-e/pin-project/pull/53. struct __Struct<'pin, T, U> { __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'pin, (T, U)>, __field0: T, @@ -87,42 +96,43 @@ fn __unpin_scope_Struct() { __Struct<'pin, T, U>: ::core::marker::Unpin { } -} -// Ensure that struct does not implement `Drop`. -// -// There are two possible cases: -// 1. The user type does not implement Drop. In this case, -// the first blanked impl will not apply to it. This code -// will compile, as there is only one impl of MustNotImplDrop for the user type -// 2. The user type does impl Drop. This will make the blanket impl applicable, -// which will then conflict with the explicit MustNotImplDrop impl below. -// This will result in a compilation error, which is exactly what we want. -trait StructMustNotImplDrop {} -#[allow(clippy::drop_bounds)] -impl StructMustNotImplDrop for T {} -#[allow(single_use_lifetimes)] -impl StructMustNotImplDrop for Struct {} + // Ensure that struct does not implement `Drop`. + // + // If you attempt to provide an Drop impl, the blanket impl will + // then apply to your type, causing a compile-time error due to + // the conflict with the second impl. + trait StructMustNotImplDrop {} + #[allow(clippy::drop_bounds)] + impl StructMustNotImplDrop for T {} + #[allow(single_use_lifetimes)] + impl StructMustNotImplDrop for Struct {} + // A dummy impl of `PinnedDrop`, to ensure that users don't accidentally + // write a non-functional `PinnedDrop` impls. + #[allow(single_use_lifetimes)] + impl ::pin_project::__private::PinnedDrop for Struct { + unsafe fn drop(self: ::core::pin::Pin<&mut Self>) {} + } -// Ensure that it's impossible to use pin projections on a #[repr(packed)] struct. -// -// Taking a reference to a packed field is unsafe, and applying -// #[deny(safe_packed_borrows)] makes sure that doing this without -// an 'unsafe' block (which we deliberately do not generate) -// is a hard error. -// -// If the struct ends up having #[repr(packed)] applied somehow, -// this will generate an (unfriendly) error message. Under all reasonable -// circumstances, we'll detect the #[repr(packed)] attribute, and generate -// a much nicer error above. -// -// See https://github.com/taiki-e/pin-project/pull/34 for more details. -#[allow(single_use_lifetimes)] -#[allow(non_snake_case)] -#[deny(safe_packed_borrows)] -fn __pin_project_assert_not_repr_packed_Struct(val: &Struct) { - &val.pinned; - &val.unpinned; -} + // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct. + // + // Taking a reference to a packed field is unsafe, and applying + // #[deny(safe_packed_borrows)] makes sure that doing this without + // an 'unsafe' block (which we deliberately do not generate) + // is a hard error. + // + // If the struct ends up having #[repr(packed)] applied somehow, + // this will generate an (unfriendly) error message. Under all reasonable + // circumstances, we'll detect the #[repr(packed)] attribute, and generate + // a much nicer error above. + // + // See https://github.com/taiki-e/pin-project/pull/34 for more details. + #[allow(single_use_lifetimes)] + #[deny(safe_packed_borrows)] + fn __assert_not_repr_packed(val: &Struct) { + &val.pinned; + &val.unpinned; + } +}; fn main() {} diff --git a/examples/unsafe_unpin-expanded.rs b/examples/unsafe_unpin-expanded.rs index acb3ee83..53fe3dcb 100644 --- a/examples/unsafe_unpin-expanded.rs +++ b/examples/unsafe_unpin-expanded.rs @@ -29,62 +29,74 @@ pub struct Foo { #[allow(clippy::mut_mut)] // This lint warns `&mut &mut `. #[allow(dead_code)] // This lint warns unused fields/variants. -pub(crate) struct __FooProjection<'pin, T, U> { +pub(crate) struct __FooProjection<'pin, T, U> +where + Foo: 'pin, +{ pinned: ::core::pin::Pin<&'pin mut (T)>, unpinned: &'pin mut (U), } #[allow(dead_code)] // This lint warns unused fields/variants. -pub(crate) struct __FooProjectionRef<'pin, T, U> { +pub(crate) struct __FooProjectionRef<'pin, T, U> +where + Foo: 'pin, +{ pinned: ::core::pin::Pin<&'pin (T)>, unpinned: &'pin (U), } -impl Foo { - pub(crate) fn project<'pin>( - self: ::core::pin::Pin<&'pin mut Self>, - ) -> __FooProjection<'pin, T, U> { - unsafe { - let Foo { pinned, unpinned } = self.get_unchecked_mut(); - __FooProjection { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned } +#[allow(non_upper_case_globals)] +const __SCOPE_Foo: () = { + impl Foo { + pub(crate) fn project<'pin>( + self: ::core::pin::Pin<&'pin mut Self>, + ) -> __FooProjection<'pin, T, U> { + unsafe { + let Foo { pinned, unpinned } = self.get_unchecked_mut(); + __FooProjection { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned } + } } - } - pub(crate) fn project_ref<'pin>( - self: ::core::pin::Pin<&'pin Self>, - ) -> __FooProjectionRef<'pin, T, U> { - unsafe { - let Foo { pinned, unpinned } = self.get_ref(); - __FooProjectionRef { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned } + pub(crate) fn project_ref<'pin>( + self: ::core::pin::Pin<&'pin Self>, + ) -> __FooProjectionRef<'pin, T, U> { + unsafe { + let Foo { pinned, unpinned } = self.get_ref(); + __FooProjectionRef { pinned: ::core::pin::Pin::new_unchecked(pinned), unpinned } + } } } -} -unsafe impl UnsafeUnpin for Foo {} + unsafe impl UnsafeUnpin for Foo {} -#[allow(single_use_lifetimes)] -impl<'pin, T, U> ::core::marker::Unpin for Foo where - ::pin_project::__private::Wrapper<'pin, Self>: ::pin_project::UnsafeUnpin -{ -} + #[allow(single_use_lifetimes)] + impl<'pin, T, U> ::core::marker::Unpin for Foo where + ::pin_project::__private::Wrapper<'pin, Self>: ::pin_project::UnsafeUnpin + { + } -// Ensure that struct does not implement `Drop`. -// -// See ./struct-default-expanded.rs for details. -trait FooMustNotImplDrop {} -#[allow(clippy::drop_bounds)] -impl FooMustNotImplDrop for T {} -#[allow(single_use_lifetimes)] -impl FooMustNotImplDrop for Foo {} + // Ensure that struct does not implement `Drop`. + // + // See ./struct-default-expanded.rs for details. + trait FooMustNotImplDrop {} + #[allow(clippy::drop_bounds)] + impl FooMustNotImplDrop for T {} + #[allow(single_use_lifetimes)] + impl FooMustNotImplDrop for Foo {} + #[allow(single_use_lifetimes)] + impl ::pin_project::__private::PinnedDrop for Foo { + unsafe fn drop(self: ::core::pin::Pin<&mut Self>) {} + } -// 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(val: &Foo) { - &val.pinned; - &val.unpinned; -} + // 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(val: &Foo) { + &val.pinned; + &val.unpinned; + } +}; fn main() {} diff --git a/pin-project-internal/src/lib.rs b/pin-project-internal/src/lib.rs index ba7abbb3..aa0eb27f 100644 --- a/pin-project-internal/src/lib.rs +++ b/pin-project-internal/src/lib.rs @@ -12,19 +12,6 @@ // mem::take requires Rust 1.40 #![allow(clippy::mem_replace_with_default)] #![allow(clippy::needless_doctest_main)] -// While this crate supports stable Rust, it currently requires -// nightly Rust in order for rustdoc to correctly document auto-generated -// `Unpin` impls. This does not affect the runtime functionality of this crate, -// nor does it affect the safety of the api provided by this crate. -// -// This is disabled by default and can be enabled using -// `--cfg pin_project_show_unpin_struct` in RUSTFLAGS. -// -// Refs: -// * https://github.com/taiki-e/pin-project/pull/53#issuecomment-525906867 -// * https://github.com/taiki-e/pin-project/pull/70 -// * https://github.com/rust-lang/rust/issues/63281 -#![cfg_attr(pin_project_show_unpin_struct, feature(proc_macro_def_site))] // older compilers require explicit `extern crate`. #[allow(unused_extern_crates)] diff --git a/pin-project-internal/src/pin_project/derive.rs b/pin-project-internal/src/pin_project/derive.rs index 30318f04..7d573c26 100644 --- a/pin-project-internal/src/pin_project/derive.rs +++ b/pin-project-internal/src/pin_project/derive.rs @@ -11,27 +11,68 @@ use crate::utils::*; use super::PIN; pub(super) fn parse_derive(input: TokenStream) -> Result { - match syn::parse2(input)? { + let mut item = syn::parse2(input)?; + + match &mut item { Item::Struct(ItemStruct { attrs, vis, ident, generics, fields, .. }) => { - validate_struct(&ident, &fields)?; + validate_struct(ident, fields)?; let mut cx = Context::new(attrs, vis, ident, generics)?; - let packed_check = cx.ensure_not_packed(&fields)?; - let mut proj_items = cx.parse_struct(&fields)?; - proj_items.extend(packed_check); - proj_items.extend(cx.make_unpin_impl()); - proj_items.extend(cx.make_drop_impl()); + // Do this first for a better error message. + let packed_check = cx.ensure_not_packed(fields)?; + + let (mut proj_items, proj_impl) = cx.parse_struct(fields)?; + let unpin_impl = cx.make_unpin_impl(); + let drop_impl = cx.make_drop_impl(); + + let dummy_const = format_ident!("__SCOPE_{}", ident); + proj_items.extend(quote! { + // All items except projected types are generated inside a `const` scope. + // This makes it impossible for user code to refer to these types. + // However, this prevents Rustdoc from displaying docs for any + // of our types. In particular, users cannot see the + // automatically generated `Unpin` impl for the '__UnpinStruct' types + // + // Previously, we provided a flag to correctly document the + // automatically generated `Unpin` impl by using def-site hygiene, + // but it is now removed. + // + // Refs: + // * https://github.com/rust-lang/rust/issues/63281 + // * https://github.com/taiki-e/pin-project/pull/53#issuecomment-525906867 + // * https://github.com/taiki-e/pin-project/pull/70 + #[allow(non_upper_case_globals)] + const #dummy_const: () = { + #proj_impl + #unpin_impl + #drop_impl + #packed_check + }; + }); + Ok(proj_items) } Item::Enum(ItemEnum { attrs, vis, ident, generics, brace_token, variants, .. }) => { - validate_enum(brace_token, &variants)?; + validate_enum(*brace_token, variants)?; let mut cx = Context::new(attrs, vis, ident, generics)?; - // We don't need to check for '#[repr(packed)]', + // We don't need to check for `#[repr(packed)]`, // since it does not apply to enums. - let mut proj_items = cx.parse_enum(&variants)?; - proj_items.extend(cx.make_unpin_impl()); - proj_items.extend(cx.make_drop_impl()); + + let (mut proj_items, proj_impl) = cx.parse_enum(variants)?; + let unpin_impl = cx.make_unpin_impl(); + let drop_impl = cx.make_drop_impl(); + + let dummy_const = format_ident!("__SCOPE_{}", ident); + proj_items.extend(quote! { + #[allow(non_upper_case_globals)] + const #dummy_const: () = { + #proj_impl + #unpin_impl + #drop_impl + }; + }); + Ok(proj_items) } item => Err(error!(item, "#[pin_project] attribute may only be used on structs or enums")), @@ -141,7 +182,7 @@ impl Parse for Args { } // If this fails, it means that there is a `#[pin]` attribute - // inserted by something other than #[pin_project] attribute. + // inserted by something other than `#[pin_project]` attribute. Err(error!(TokenStream::new(), DUPLICATE_PIN)) } @@ -174,15 +215,15 @@ impl Parse for Args { } } -struct OriginalType { +struct OriginalType<'a> { /// Attributes of the original type. - attrs: Vec, + attrs: &'a [Attribute], /// Visibility of the original type. - vis: Visibility, + vis: &'a Visibility, /// Name of the original type. - ident: Ident, + ident: &'a Ident, /// Generics of the original type. - generics: Generics, + generics: &'a Generics, } struct ProjectedType { @@ -201,8 +242,8 @@ struct ProjectedType { where_clause: WhereClause, } -struct Context { - orig: OriginalType, +struct Context<'a> { + orig: OriginalType<'a>, proj: ProjectedType, /// Types of the pinned fields. pinned_fields: Vec, @@ -212,14 +253,14 @@ struct Context { unsafe_unpin: Option, } -impl Context { +impl<'a> Context<'a> { fn new( - attrs: Vec, - vis: Visibility, - ident: Ident, - mut generics: Generics, + attrs: &'a [Attribute], + vis: &'a Visibility, + ident: &'a Ident, + generics: &'a mut Generics, ) -> Result { - let Args { pinned_drop, unsafe_unpin } = Args::get(&attrs)?; + let Args { pinned_drop, unsafe_unpin } = Args::get(attrs)?; { let ty_generics = generics.split_for_impl().1; @@ -246,9 +287,9 @@ impl Context { Ok(Self { proj: ProjectedType { - vis: determine_visibility(&vis), - mut_ident: proj_ident(&ident, Mutable), - ref_ident: proj_ident(&ident, Immutable), + vis: determine_visibility(vis), + mut_ident: proj_ident(ident, Mutable), + ref_ident: proj_ident(ident, Immutable), lifetime, generics: proj_generics, where_clause, @@ -260,14 +301,14 @@ impl Context { }) } - fn parse_struct(&mut self, fields: &Fields) -> Result { + fn parse_struct(&mut self, fields: &Fields) -> Result<(TokenStream, TokenStream)> { let (proj_pat, proj_init, proj_fields, proj_ref_fields) = match fields { Fields::Named(fields) => self.visit_named(fields)?, Fields::Unnamed(fields) => self.visit_unnamed(fields)?, Fields::Unit => unreachable!(), }; - let orig_ident = &self.orig.ident; + let orig_ident = self.orig.ident; let proj_ident = &self.proj.mut_ident; let proj_ref_ident = &self.proj.ref_ident; let vis = &self.proj.vis; @@ -286,7 +327,7 @@ impl Context { Fields::Unit => unreachable!(), }; - let mut proj_items = quote! { + let proj_items = quote! { #[allow(clippy::mut_mut)] // This lint warns `&mut &mut `. #[allow(dead_code)] // This lint warns unused fields/variants. #vis struct #proj_ident #proj_generics #where_clause_fields @@ -302,13 +343,12 @@ impl Context { let #orig_ident #proj_pat = self.get_ref(); #proj_ref_ident #proj_init }; + let proj_impl = self.make_proj_impl(&proj_body, &proj_ref_body); - proj_items.extend(self.make_proj_impl(&proj_body, &proj_ref_body)); - - Ok(proj_items) + Ok((proj_items, proj_impl)) } - fn parse_enum(&mut self, variants: &Variants) -> Result { + fn parse_enum(&mut self, variants: &Variants) -> Result<(TokenStream, TokenStream)> { let (proj_variants, proj_ref_variants, proj_arms, proj_ref_arms) = self.visit_variants(variants)?; @@ -318,7 +358,7 @@ impl Context { let proj_generics = &self.proj.generics; let where_clause = &self.proj.where_clause; - let mut proj_items = quote! { + let proj_items = quote! { #[allow(clippy::mut_mut)] // This lint warns `&mut &mut `. #[allow(dead_code)] // This lint warns unused fields/variants. #vis enum #proj_ident #proj_generics #where_clause { @@ -340,10 +380,9 @@ impl Context { #proj_ref_arms } }; + let proj_impl = self.make_proj_impl(&proj_body, &proj_ref_body); - proj_items.extend(self.make_proj_impl(&proj_body, &proj_ref_body)); - - Ok(proj_items) + Ok((proj_items, proj_impl)) } fn visit_variants( @@ -363,7 +402,7 @@ impl Context { } }; - let orig_ident = &self.orig.ident; + let orig_ident = self.orig.ident; let proj_ident = &self.proj.mut_ident; let proj_ref_ident = &self.proj.ref_ident; proj_variants.extend(quote! { @@ -482,7 +521,7 @@ impl Context { fn make_unpin_impl(&mut self) -> TokenStream { if let Some(unsafe_unpin) = self.unsafe_unpin { let mut proj_generics = self.proj.generics.clone(); - let orig_ident = &self.orig.ident; + let orig_ident = self.orig.ident; let lifetime = &self.proj.lifetime; let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site()); @@ -503,20 +542,6 @@ impl Context { } } else { let mut full_where_clause = self.orig.generics.where_clause.as_ref().cloned().unwrap(); - let orig_ident = &self.orig.ident; - - let make_span = || { - #[cfg(pin_project_show_unpin_struct)] - { - proc_macro::Span::def_site().into() - } - #[cfg(not(pin_project_show_unpin_struct))] - { - Span::call_site() - } - }; - - let struct_ident = format_ident!("__{}", orig_ident, span = make_span()); // Generate a field in our new struct for every // pinned field in the original type. @@ -552,7 +577,7 @@ impl Context { // ``` // // This ensures that any unused type parameters - // don't end up with Unpin bounds. + // don't end up with `Unpin` bounds. let lifetime_fields: Vec<_> = self .orig .generics @@ -566,9 +591,9 @@ impl Context { }) .collect(); - let scope_ident = format_ident!("__unpin_scope_{}", orig_ident); - - let vis = &self.orig.vis; + let orig_ident = self.orig.ident; + let struct_ident = format_ident!("__{}", orig_ident); + let vis = self.orig.vis; let lifetime = &self.proj.lifetime; let type_params: Vec<_> = self.orig.generics.type_params().map(|t| &t.ident).collect(); let proj_generics = &self.proj.generics; @@ -580,19 +605,17 @@ impl Context { }); let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site()); - let inner_data = quote! { + quote! { // This needs to have the same visibility as the original type, // due to the limitations of the 'public in private' error. // - // Out goal is to implement the public trait Unpin for + // Our goal is to implement the public trait `Unpin` for // a potentially public user type. Because of this, rust // requires that any types mentioned in the where clause of - // our Unpin impl also be public. This means that our generated - // 'UnpinStruct' type must also be public. However, we take - // steps to ensure that the user can never actually reference - // this 'public' type. These steps are described below. - // - // See also https://github.com/taiki-e/pin-project/pull/53. + // our `Unpin` impl also be public. This means that our generated + // `__UnpinStruct` type must also be public. + // However, we ensure that the user can never actually reference + // this 'public' type by creating this type in the inside of `const`. #vis struct #struct_ident #proj_generics #where_clause { __pin_project_use_generics: ::pin_project::#private::AlwaysUnpin<#lifetime, (#(#type_params),*)>, @@ -601,42 +624,21 @@ impl Context { } impl #impl_generics ::core::marker::Unpin for #orig_ident #ty_generics #full_where_clause {} - }; - - if cfg!(pin_project_show_unpin_struct) { - // On nightly, we use def-site hygiene to make it impossible - // for user code to refer to any of the types we define. - // This allows us to omit wrapping the generated types - // in an fn() scope, allowing rustdoc to properly document - // them. - inner_data - } else { - // When we're not on nightly, we need to create an enclosing fn() scope - // for all of our generated items. This makes it impossible for - // user code to refer to any of our generated types, but has - // the advantage of preventing Rustdoc from displaying - // docs for any of our types. In particular, users cannot see - // the automatically generated Unpin impl for the 'UnpinStruct$Name' types. - quote! { - #[allow(non_snake_case)] - fn #scope_ident() { - #inner_data - } - } } } } /// Creates `Drop` implementation for original type. fn make_drop_impl(&self) -> TokenStream { - let ident = &self.orig.ident; + let ident = self.orig.ident; let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl(); let private = Ident::new(CURRENT_PRIVATE_MODULE, Span::call_site()); if let Some(pinned_drop) = self.pinned_drop { // Make the error message highlight `PinnedDrop` argument. // See https://github.com/taiki-e/pin-project/issues/16#issuecomment-513586812 - // for why this is only for the span of function calls, not the entire `impl` block. + // for why this is only for the span of function calls, + // not the entire `impl` block. let call_drop = quote_spanned! { pinned_drop => ::pin_project::#private::PinnedDrop::drop(pinned_self) }; @@ -649,7 +651,7 @@ impl Context { // 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 + // 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 { #call_drop; @@ -658,7 +660,7 @@ impl Context { } } } else { - // If the user does not provide a pinned_drop impl, + // If the user does not provide a `PinnedDrop` impl, // we need to ensure that they don't provide a `Drop` impl of their // own. // Based on https://github.com/upsuper/assert-impl/blob/f503255b292ab0ba8d085b657f4065403cfa46eb/src/lib.rs#L80-L87 @@ -697,7 +699,7 @@ impl Context { // To ensure that users don't accidentally write a non-functional `PinnedDrop` // impls, we emit one ourselves. If the user ends up writing a `PinnedDrop` impl, // they'll get a "conflicting implementations of trait" error when coherence - // checks are run + // checks are run. #[allow(single_use_lifetimes)] impl #impl_generics ::pin_project::#private::PinnedDrop for #ident #ty_generics #where_clause { unsafe fn drop(self: ::core::pin::Pin<&mut Self>) {} @@ -710,7 +712,7 @@ impl Context { fn make_proj_impl(&self, proj_body: &TokenStream, proj_ref_body: &TokenStream) -> TokenStream { let vis = &self.proj.vis; let lifetime = &self.proj.lifetime; - let orig_ident = &self.orig.ident; + let orig_ident = self.orig.ident; let proj_ident = &self.proj.mut_ident; let proj_ref_ident = &self.proj.ref_ident; @@ -764,38 +766,40 @@ impl Context { // Workaround for https://github.com/taiki-e/pin-project/issues/32 // Through the tricky use of proc macros, it's possible to bypass - // the above check for the 'repr' attribute. - // To ensure that it's impossible to use pin projections on a #[repr(packed)] + // the above check for the `repr` attribute. + // To ensure that it's impossible to use pin projections on a `#[repr(packed)]` // struct, we generate code like this: // + // ```rust // #[deny(safe_packed_borrows)] - // fn enforce_not_packed_for_MyStruct(val: &MyStruct) { - // let _field1 = &val.field1; - // let _field2 = &val.field2; - // ... - // let _fieldn = &val.fieldn; + // fn assert_not_repr_packed(val: &MyStruct) { + // let _field1 = &val.field1; + // let _field2 = &val.field2; + // ... + // let _fieldn = &val.fieldn; // } + // ``` // // Taking a reference to a packed field is unsafe, and applying - // #[deny(safe_packed_borrows)] makes sure that doing this without - // an 'unsafe' block (which we deliberately do not generate) + // `#[deny(safe_packed_borrows)]` makes sure that doing this without + // an `unsafe` block (which we deliberately do not generate) // is a hard error. // - // If the struct ends up having #[repr(packed)] applied somehow, + // If the struct ends up having `#[repr(packed)]` applied somehow, // this will generate an (unfriendly) error message. Under all reasonable - // circumstances, we'll detect the #[repr(packed)] attribute, and generate + // circumstances, we'll detect the `#[repr(packed)]` attribute, and generate // a much nicer error above. // // There is one exception: If the type of a struct field has an alignment of 1 // (e.g. u8), it is always safe to take a reference to it, even if the struct - // is #[repr(packed)]. If the struct is composed entirely of types of alignment 1, - // our generated method will not trigger an error if the struct is #[repr(packed)] + // is `#[repr(packed)]`. If the struct is composed entirely of types of alignment 1, + // our generated method will not trigger an error if the struct is `#[repr(packed)]`. // - // Fortunately, this should have no observable consequence - #[repr(packed)] + // Fortunately, this should have no observable consequence - `#[repr(packed)]` // is essentially a no-op on such a type. Nevertheless, we include a test // to ensure that the compiler doesn't ever try to copy the fields on // such a struct when trying to drop it - which is reason we prevent - // #[repr(packed)] in the first place. + // `#[repr(packed)]` in the first place. // // See also https://github.com/taiki-e/pin-project/pull/34. let mut field_refs = vec![]; @@ -815,18 +819,15 @@ impl Context { }); } } - Fields::Unit => {} + Fields::Unit => unreachable!(), } let (impl_generics, ty_generics, where_clause) = self.orig.generics.split_for_impl(); - - let struct_name = &self.orig.ident; - let method_name = format_ident!("__pin_project_assert_not_repr_packed_{}", self.orig.ident); + let ident = self.orig.ident; Ok(quote! { #[allow(single_use_lifetimes)] - #[allow(non_snake_case)] #[deny(safe_packed_borrows)] - fn #method_name #impl_generics (val: &#struct_name #ty_generics) #where_clause { + fn __assert_not_repr_packed #impl_generics (val: &#ident #ty_generics) #where_clause { #(#field_refs)* } }) diff --git a/tests/compiletest.rs b/tests/compiletest.rs index cf3986fc..22aaa943 100644 --- a/tests/compiletest.rs +++ b/tests/compiletest.rs @@ -1,4 +1,3 @@ -#![cfg(pin_project_show_unpin_struct)] #![warn(unsafe_code)] #![warn(rust_2018_idioms, single_use_lifetimes)] diff --git a/tests/ui/cfg/cfg_attr-unpin.stderr b/tests/ui/cfg/cfg_attr-unpin.stderr index 8879d020..ce31c249 100644 --- a/tests/ui/cfg/cfg_attr-unpin.stderr +++ b/tests/ui/cfg/cfg_attr-unpin.stderr @@ -16,7 +16,7 @@ error[E0277]: `std::marker::PhantomPinned` cannot be unpinned | ----- required by this bound in `is_unpin` ... 20 | is_unpin::>(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__Bar<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__SCOPE_Bar::__Bar<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | - = note: required because it appears within the type `__Bar<'_, std::marker::PhantomPinned>` + = note: required because it appears within the type `__SCOPE_Bar::__Bar<'_, std::marker::PhantomPinned>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `Bar` diff --git a/tests/ui/cfg/proper_unpin.stderr b/tests/ui/cfg/proper_unpin.stderr index 1f58ea21..407d900f 100644 --- a/tests/ui/cfg/proper_unpin.stderr +++ b/tests/ui/cfg/proper_unpin.stderr @@ -5,7 +5,7 @@ error[E0277]: `std::marker::PhantomPinned` cannot be unpinned | ----- required by this bound in `is_unpin` ... 27 | is_unpin::>(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__Bar<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__SCOPE_Bar::__Bar<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | - = note: required because it appears within the type `__Bar<'_, std::marker::PhantomPinned>` + = note: required because it appears within the type `__SCOPE_Bar::__Bar<'_, std::marker::PhantomPinned>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `Bar` diff --git a/tests/ui/pin_project/add-pinned-field.stderr b/tests/ui/pin_project/add-pinned-field.stderr index 3de6f4ac..db07a748 100644 --- a/tests/ui/pin_project/add-pinned-field.stderr +++ b/tests/ui/pin_project/add-pinned-field.stderr @@ -5,9 +5,9 @@ error[E0277]: `std::marker::PhantomPinned` cannot be unpinned | ----- required by this bound in `is_unpin` ... 21 | is_unpin::(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^ within `__Foo<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | ^^^^^^^^^^^^^^^ within `__SCOPE_Foo::__Foo<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | - = note: required because it appears within the type `__Foo<'_>` + = note: required because it appears within the type `__SCOPE_Foo::__Foo<'_>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo` error[E0277]: `std::marker::PhantomPinned` cannot be unpinned @@ -17,7 +17,7 @@ error[E0277]: `std::marker::PhantomPinned` cannot be unpinned | ----- required by this bound in `is_unpin` ... 22 | is_unpin::(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^ within `__Bar<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | ^^^^^^^^^^^^^^^ within `__SCOPE_Bar::__Bar<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | - = note: required because it appears within the type `__Bar<'_>` + = note: required because it appears within the type `__SCOPE_Bar::__Bar<'_>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `Bar` diff --git a/tests/ui/pin_project/conflict-drop.stderr b/tests/ui/pin_project/conflict-drop.stderr index 1724fcc0..e0b72c14 100644 --- a/tests/ui/pin_project/conflict-drop.stderr +++ b/tests/ui/pin_project/conflict-drop.stderr @@ -1,4 +1,4 @@ -error[E0119]: conflicting implementations of trait `FooMustNotImplDrop` for type `Foo<_, _>`: +error[E0119]: conflicting implementations of trait `__SCOPE_Foo::FooMustNotImplDrop` for type `Foo<_, _>`: --> $DIR/conflict-drop.rs:4:1 | 4 | #[pin_project] //~ ERROR E0119 diff --git a/tests/ui/pin_project/overlapping_unpin_struct.stderr b/tests/ui/pin_project/overlapping_unpin_struct.stderr index 60f4116d..d0fd4a9c 100644 --- a/tests/ui/pin_project/overlapping_unpin_struct.stderr +++ b/tests/ui/pin_project/overlapping_unpin_struct.stderr @@ -5,7 +5,7 @@ error[E0277]: `std::marker::PhantomPinned` cannot be unpinned | ----- required by this bound in `is_unpin` ... 17 | is_unpin::>(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__Foo<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__SCOPE_Foo::__Foo<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | - = note: required because it appears within the type `__Foo<'_, std::marker::PhantomPinned>` + = note: required because it appears within the type `__SCOPE_Foo::__Foo<'_, std::marker::PhantomPinned>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo` diff --git a/tests/ui/pin_project/proper_unpin.stderr b/tests/ui/pin_project/proper_unpin.stderr index 73fd2894..91428876 100644 --- a/tests/ui/pin_project/proper_unpin.stderr +++ b/tests/ui/pin_project/proper_unpin.stderr @@ -5,10 +5,10 @@ error[E0277]: `std::marker::PhantomPinned` cannot be unpinned | ----- required by this bound in `is_unpin` ... 31 | is_unpin::>(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__Foo<'_, std::marker::PhantomPinned, ()>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__SCOPE_Foo::__Foo<'_, std::marker::PhantomPinned, ()>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | = note: required because it appears within the type `Inner` - = note: required because it appears within the type `__Foo<'_, std::marker::PhantomPinned, ()>` + = note: required because it appears within the type `__SCOPE_Foo::__Foo<'_, std::marker::PhantomPinned, ()>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo` error[E0277]: `std::marker::PhantomPinned` cannot be unpinned @@ -18,10 +18,10 @@ error[E0277]: `std::marker::PhantomPinned` cannot be unpinned | ----- required by this bound in `is_unpin` ... 33 | is_unpin::>(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__Foo<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `__SCOPE_Foo::__Foo<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | = note: required because it appears within the type `Inner` - = note: required because it appears within the type `__Foo<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>` + = note: required because it appears within the type `__SCOPE_Foo::__Foo<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo` error[E0277]: `std::marker::PhantomPinned` cannot be unpinned @@ -31,7 +31,7 @@ error[E0277]: `std::marker::PhantomPinned` cannot be unpinned | ----- required by this bound in `is_unpin` ... 35 | is_unpin::(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `__TrivialBounds<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `__SCOPE_TrivialBounds::__TrivialBounds<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | - = note: required because it appears within the type `__TrivialBounds<'_>` + = note: required because it appears within the type `__SCOPE_TrivialBounds::__TrivialBounds<'_>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `TrivialBounds` diff --git a/tests/ui/pin_project/unpin_sneaky.stderr b/tests/ui/pin_project/unpin_sneaky.stderr index d96050bb..0637a665 100644 --- a/tests/ui/pin_project/unpin_sneaky.stderr +++ b/tests/ui/pin_project/unpin_sneaky.stderr @@ -3,11 +3,6 @@ error[E0412]: cannot find type `__Foo` in this scope | 9 | impl Unpin for __Foo {} //~ ERROR E0412,E0321 | ^^^^^ not found in this scope - | -help: possible candidate is found in another module, you can import it into scope - | -1 | use crate::__Foo; - | error[E0321]: cross-crate traits with a default impl, like `std::marker::Unpin`, can only be implemented for a struct/enum type, not `[type error]` --> $DIR/unpin_sneaky.rs:9:1