From 9d0e875faf16e3ded980c1209446bd439e232712 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 26 Sep 2019 19:33:17 +0900 Subject: [PATCH] Add a dummy lifetime to UnpinStruct --- examples/enum-default-expanded.rs | 15 +++--- examples/pinned_drop-expanded.rs | 15 +++--- examples/struct-default-expanded.rs | 13 ++--- examples/unsafe_unpin-expanded.rs | 1 + .../src/pin_project/derive.rs | 43 +++++++++------- src/lib.rs | 8 +++ tests/pin_project.rs | 11 +++- tests/ui/cfg/proper_unpin.rs | 3 +- tests/ui/cfg/proper_unpin.stderr | 10 ++-- tests/ui/pin_project/proper_unpin.rs | 25 ++++++++-- tests/ui/pin_project/proper_unpin.stderr | 50 +++++++++++++++---- tests/ui/unsafe_unpin/proper_unpin.rs | 3 ++ tests/ui/unsafe_unpin/proper_unpin.stderr | 16 +++--- .../trivial_bounds-feature-gate.rs | 7 ++- .../trivial_bounds-feature-gate.stderr | 16 ------ tests/ui/unstable-features/trivial_bounds.rs | 3 ++ tests/unsafe_unpin.rs | 15 +++--- 17 files changed, 158 insertions(+), 96 deletions(-) delete mode 100644 tests/ui/unstable-features/trivial_bounds-feature-gate.stderr diff --git a/examples/enum-default-expanded.rs b/examples/enum-default-expanded.rs index 0033c718..d468c69c 100644 --- a/examples/enum-default-expanded.rs +++ b/examples/enum-default-expanded.rs @@ -19,7 +19,7 @@ use pin_project::pin_project; enum Enum { - Pinned(T), + Pinned(/* #[pin] */ T), Unpinned(U), } @@ -63,17 +63,16 @@ impl Enum { // for details. #[allow(non_snake_case)] fn __unpin_scope_Enum() { - struct AlwaysUnpinEnum { - val: ::core::marker::PhantomData, - } - impl ::core::marker::Unpin for AlwaysUnpinEnum {} #[allow(dead_code)] #[doc(hidden)] - struct __UnpinStructEnum { - __pin_project_use_generics: AlwaysUnpinEnum<(T, U)>, + struct __UnpinStructEnum<'_pin, T, U> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'_pin, (T, U)>, __field0: T, } - impl ::core::marker::Unpin for Enum where __UnpinStructEnum: ::core::marker::Unpin {} + impl<'_pin, T, U> ::core::marker::Unpin for Enum where + __UnpinStructEnum<'_pin, T, U>: ::core::marker::Unpin + { + } } // Ensure that enum does not implement `Drop`. diff --git a/examples/pinned_drop-expanded.rs b/examples/pinned_drop-expanded.rs index 593069c5..9557fb82 100644 --- a/examples/pinned_drop-expanded.rs +++ b/examples/pinned_drop-expanded.rs @@ -28,6 +28,7 @@ use std::pin::Pin; pub struct Foo<'a, T> { was_dropped: &'a mut bool, + // #[pin] field: T, } @@ -109,19 +110,17 @@ impl ::pin_project::__private::PinnedDrop for Foo<'_, T> { // for details. #[allow(non_snake_case)] fn __unpin_scope_Foo() { - struct AlwaysUnpinFoo { - val: ::core::marker::PhantomData, - } - impl ::core::marker::Unpin for AlwaysUnpinFoo {} #[allow(dead_code)] #[doc(hidden)] - pub struct __UnpinStructFoo<'a, T> { - __pin_project_use_generics: AlwaysUnpinFoo<(T)>, + pub struct __UnpinStructFoo<'_pin, 'a, T> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'_pin, (T)>, __field0: T, __lifetime0: &'a (), } - impl<'a, T> ::core::marker::Unpin for Foo<'a, T> where __UnpinStructFoo<'a, T>: ::core::marker::Unpin - {} + impl<'_pin, 'a, T> ::core::marker::Unpin for Foo<'a, T> where + __UnpinStructFoo<'_pin, 'a, T>: ::core::marker::Unpin + { + } } // Ensure that it's impossible to use pin projections on a #[repr(packed)] struct. diff --git a/examples/struct-default-expanded.rs b/examples/struct-default-expanded.rs index 748b1420..2834ee03 100644 --- a/examples/struct-default-expanded.rs +++ b/examples/struct-default-expanded.rs @@ -20,6 +20,7 @@ use pin_project::pin_project; struct Struct { + // #[pin] pinned: T, unpinned: U, } @@ -86,18 +87,14 @@ impl Struct { // See also https://github.com/taiki-e/pin-project/pull/53. #[allow(non_snake_case)] fn __unpin_scope_Struct() { - struct AlwaysUnpinStruct { - val: ::core::marker::PhantomData, - } - impl ::core::marker::Unpin for AlwaysUnpinStruct {} #[allow(dead_code)] #[doc(hidden)] - struct __UnpinStructStruct { - __pin_project_use_generics: AlwaysUnpinStruct<(T, U)>, + struct __UnpinStructStruct<'_pin, T, U> { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<'_pin, (T, U)>, __field0: T, } - impl ::core::marker::Unpin for Struct where - __UnpinStructStruct: ::core::marker::Unpin + impl<'_pin, T, U> ::core::marker::Unpin for Struct where + __UnpinStructStruct<'_pin, T, U>: ::core::marker::Unpin { } } diff --git a/examples/unsafe_unpin-expanded.rs b/examples/unsafe_unpin-expanded.rs index b7c5975f..349fb93d 100644 --- a/examples/unsafe_unpin-expanded.rs +++ b/examples/unsafe_unpin-expanded.rs @@ -22,6 +22,7 @@ use pin_project::{pin_project, UnsafeUnpin}; pub struct Foo { + // #[pin] pinned: T, unpinned: U, } diff --git a/pin-project-internal/src/pin_project/derive.rs b/pin-project-internal/src/pin_project/derive.rs index 1356d1ab..2a130924 100644 --- a/pin-project-internal/src/pin_project/derive.rs +++ b/pin-project-internal/src/pin_project/derive.rs @@ -1,8 +1,8 @@ -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote}; use syn::{parse::Nothing, *}; -use crate::utils::{Variants, VecExt}; +use crate::utils::{self, proj_lifetime_name, Variants, VecExt, DEFAULT_LIFETIME_NAME}; use super::PIN; @@ -34,13 +34,27 @@ struct DeriveContext { /// Generics of the original type. generics: Generics, + /// Lifetime on the generated projected type. + lifetime: Lifetime, + /// Types of the pinned fields. pinned_fields: Vec, } impl DeriveContext { fn new(ident: Ident, vis: Visibility, generics: Generics) -> Self { - Self { ident, vis, generics, pinned_fields: Vec::new() } + let mut lifetime_name = String::from(DEFAULT_LIFETIME_NAME); + proj_lifetime_name(&mut lifetime_name, &generics.params); + let lifetime = Lifetime::new(&lifetime_name, Span::call_site()); + + Self { ident, vis, generics, lifetime, pinned_fields: Vec::new() } + } + + /// Creates the generics of projected type. + fn proj_generics(&self) -> Generics { + let mut generics = self.generics.clone(); + utils::proj_generics(&mut generics, self.lifetime.clone()); + generics } fn visit_variants(&mut self, variants: &Variants) { @@ -68,8 +82,6 @@ impl DeriveContext { fn make_unpin_impl(&mut self) -> TokenStream { let where_clause = self.generics.make_where_clause().clone(); let orig_ident = &self.ident; - let (impl_generics, ty_generics, _) = self.generics.split_for_impl(); - let type_params: Vec<_> = self.generics.type_params().map(|t| t.ident.clone()).collect(); let make_span = || { #[cfg(proc_macro_def_site)] @@ -87,7 +99,6 @@ impl DeriveContext { } else { format_ident!("__UnpinStruct{}", orig_ident) }; - let always_unpin_ident = format_ident!("AlwaysUnpin{}", orig_ident, span = make_span()); // Generate a field in our new struct for every // pinned field in the original type. @@ -138,25 +149,21 @@ impl DeriveContext { let scope_ident = format_ident!("__unpin_scope_{}", orig_ident); - let vis = &self.vis; - let full_generics = &self.generics; + let Self { vis, lifetime, .. } = &self; + let type_params: Vec<_> = self.generics.type_params().map(|t| t.ident.clone()).collect(); + let proj_generics = self.proj_generics(); + let (impl_generics, proj_ty_generics, _) = proj_generics.split_for_impl(); + let ty_generics = self.generics.split_for_impl().1; let mut full_where_clause = where_clause.clone(); let unpin_clause: WherePredicate = syn::parse_quote! { - #struct_ident #ty_generics: ::core::marker::Unpin + #struct_ident #proj_ty_generics: ::core::marker::Unpin }; - full_where_clause.predicates.push(unpin_clause); let attrs = if cfg!(proc_macro_def_site) { quote!() } else { quote!(#[doc(hidden)]) }; let inner_data = quote! { - struct #always_unpin_ident { - val: ::core::marker::PhantomData - } - - impl ::core::marker::Unpin for #always_unpin_ident {} - // This needs to have the same visibility as the original type, // due to the limitations of the 'public in private' error. // @@ -171,8 +178,8 @@ impl DeriveContext { // See also https://github.com/taiki-e/pin-project/pull/53. #[allow(dead_code)] #attrs - #vis struct #struct_ident #full_generics #where_clause { - __pin_project_use_generics: #always_unpin_ident <(#(#type_params),*)>, + #vis struct #struct_ident #proj_generics #where_clause { + __pin_project_use_generics: ::pin_project::__private::AlwaysUnpin<#lifetime, (#(#type_params),*)>, #(#fields,)* #(#lifetime_fields,)* diff --git a/src/lib.rs b/src/lib.rs index d6c38b9c..a4982aa8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -199,4 +199,12 @@ pub mod __private { #[allow(unsafe_code)] unsafe impl UnsafeUnpin for Wrapper<'_, T> where T: UnsafeUnpin {} + + // This is an internal helper struct used by `pin-project-internal`. + // + // See https://github.com/taiki-e/pin-project/pull/53 for more details. + #[doc(hidden)] + pub struct AlwaysUnpin<'a, T: ?Sized>(PhantomData, PhantomData<&'a ()>); + + impl Unpin for AlwaysUnpin<'_, T> {} } diff --git a/tests/pin_project.rs b/tests/pin_project.rs index 108e212a..53da4b4b 100644 --- a/tests/pin_project.rs +++ b/tests/pin_project.rs @@ -3,7 +3,7 @@ #![warn(rust_2018_idioms, single_use_lifetimes)] #![allow(dead_code)] -use core::pin::Pin; +use core::{marker::PhantomPinned, pin::Pin}; use pin_project::{pin_project, pinned_drop, UnsafeUnpin}; #[test] @@ -348,3 +348,12 @@ fn visibility() { let y = x.project(); let _: &mut u8 = y.b; } + +#[test] +fn trivial_bounds() { + #[pin_project] + pub struct NoGenerics { + #[pin] + field: PhantomPinned, + } +} diff --git a/tests/ui/cfg/proper_unpin.rs b/tests/ui/cfg/proper_unpin.rs index 864fbc89..568ede4e 100644 --- a/tests/ui/cfg/proper_unpin.rs +++ b/tests/ui/cfg/proper_unpin.rs @@ -24,7 +24,8 @@ struct Bar { fn is_unpin() {} fn baz() { - is_unpin::>(); // Pass + is_unpin::>(); // Ok + is_unpin::>(); // Ok is_unpin::>(); //~ ERROR E0277 } diff --git a/tests/ui/cfg/proper_unpin.stderr b/tests/ui/cfg/proper_unpin.stderr index d5a259f3..64063bff 100644 --- a/tests/ui/cfg/proper_unpin.stderr +++ b/tests/ui/cfg/proper_unpin.stderr @@ -1,15 +1,15 @@ -error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `UnpinStructBar` - --> $DIR/proper_unpin.rs:28:5 +error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `UnpinStructBar<'_, std::marker::PhantomPinned>` + --> $DIR/proper_unpin.rs:29:5 | 24 | fn is_unpin() {} | -------- ----- required by this bound in `is_unpin` ... -28 | is_unpin::>(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `UnpinStructBar`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` +29 | is_unpin::>(); //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `UnpinStructBar<'_, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | = help: the following implementations were found: - = note: required because it appears within the type `UnpinStructBar` + = note: required because it appears within the type `UnpinStructBar<'_, std::marker::PhantomPinned>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `Bar` error: aborting due to previous error diff --git a/tests/ui/pin_project/proper_unpin.rs b/tests/ui/pin_project/proper_unpin.rs index a5369e9e..5299f601 100644 --- a/tests/ui/pin_project/proper_unpin.rs +++ b/tests/ui/pin_project/proper_unpin.rs @@ -1,7 +1,7 @@ // compile-fail use pin_project::pin_project; -use std::pin::Pin; +use std::marker::PhantomPinned; struct Inner { val: T, @@ -14,10 +14,29 @@ struct Foo { other: U, } +#[pin_project] +pub struct TrivialBounds { + #[pin] + field1: PhantomPinned, +} + +#[pin_project] +struct Bar<'a, T, U> { + #[pin] + inner: &'a mut Inner, + other: U, +} + fn is_unpin() {} -fn bar() { - is_unpin::>(); //~ ERROR E0277 +fn assert_unpin() { + is_unpin::>(); //~ ERROR E0277 + is_unpin::>(); // Ok + is_unpin::>(); //~ ERROR E0277 + + is_unpin::(); //~ ERROR E0277 + + is_unpin::>(); //~ Ok } fn main() {} diff --git a/tests/ui/pin_project/proper_unpin.stderr b/tests/ui/pin_project/proper_unpin.stderr index 4938a44c..8accd861 100644 --- a/tests/ui/pin_project/proper_unpin.stderr +++ b/tests/ui/pin_project/proper_unpin.stderr @@ -1,17 +1,47 @@ -error[E0277]: the trait bound `T: std::marker::Unpin` is not satisfied in `UnpinStructFoo` - --> $DIR/proper_unpin.rs:20:5 +error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `UnpinStructFoo<'_, std::marker::PhantomPinned, ()>` + --> $DIR/proper_unpin.rs:33:5 | -17 | fn is_unpin() {} +30 | fn is_unpin() {} | -------- ----- required by this bound in `is_unpin` ... -20 | is_unpin::>(); //~ ERROR E0277 - | ^^^^^^^^^^^^^^^^^^^^^ within `UnpinStructFoo`, the trait `std::marker::Unpin` is not implemented for `T` +33 | is_unpin::>(); //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `UnpinStructFoo<'_, std::marker::PhantomPinned, ()>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | - = help: consider adding a `where T: std::marker::Unpin` bound - = note: required because it appears within the type `Inner` - = note: required because it appears within the type `UnpinStructFoo` - = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo` + = help: the following implementations were found: + + = note: required because it appears within the type `Inner` + = note: required because it appears within the type `UnpinStructFoo<'_, std::marker::PhantomPinned, ()>` + = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo` -error: aborting due to previous error +error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `UnpinStructFoo<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>` + --> $DIR/proper_unpin.rs:35:5 + | +30 | fn is_unpin() {} + | -------- ----- required by this bound in `is_unpin` +... +35 | is_unpin::>(); //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ within `UnpinStructFoo<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | + = help: the following implementations were found: + + = note: required because it appears within the type `Inner` + = note: required because it appears within the type `UnpinStructFoo<'_, std::marker::PhantomPinned, std::marker::PhantomPinned>` + = note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo` + +error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `UnpinStructTrivialBounds<'_>` + --> $DIR/proper_unpin.rs:37:5 + | +30 | fn is_unpin() {} + | -------- ----- required by this bound in `is_unpin` +... +37 | is_unpin::(); //~ ERROR E0277 + | ^^^^^^^^^^^^^^^^^^^^^^^^^ within `UnpinStructTrivialBounds<'_>`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` + | + = help: the following implementations were found: + + = note: required because it appears within the type `UnpinStructTrivialBounds<'_>` + = note: required because of the requirements on the impl of `std::marker::Unpin` for `TrivialBounds` + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unsafe_unpin/proper_unpin.rs b/tests/ui/unsafe_unpin/proper_unpin.rs index e018dbbf..52d08694 100644 --- a/tests/ui/unsafe_unpin/proper_unpin.rs +++ b/tests/ui/unsafe_unpin/proper_unpin.rs @@ -35,8 +35,11 @@ unsafe impl UnsafeUnpin for OverlappingLifetimeNames<'_, T, fn unsafe_unpin() { is_unpin::>(); //~ ERROR E0277 + is_unpin::>(); // Ok is_unpin::>(); //~ ERROR E0277 + is_unpin::(); //~ ERROR E0277 + is_unpin::>(); //~ ERROR E0277 is_unpin::>(); //~ ERROR E0277 } diff --git a/tests/ui/unsafe_unpin/proper_unpin.stderr b/tests/ui/unsafe_unpin/proper_unpin.stderr index 97059199..94bcd001 100644 --- a/tests/ui/unsafe_unpin/proper_unpin.stderr +++ b/tests/ui/unsafe_unpin/proper_unpin.stderr @@ -14,12 +14,12 @@ error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` i = note: required because of the requirements on the impl of `std::marker::Unpin` for `Blah` error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied - --> $DIR/proper_unpin.rs:38:5 + --> $DIR/proper_unpin.rs:39:5 | 6 | fn is_unpin() {} | -------- ----- required by this bound in `is_unpin` ... -38 | is_unpin::>(); //~ ERROR E0277 +39 | is_unpin::>(); //~ ERROR E0277 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | = help: the following implementations were found: @@ -29,24 +29,24 @@ error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` i = note: required because of the requirements on the impl of `std::marker::Unpin` for `Blah` error[E0277]: the trait bound `NotImplementUnsafUnpin: pin_project::UnsafeUnpin` is not satisfied - --> $DIR/proper_unpin.rs:39:16 + --> $DIR/proper_unpin.rs:41:16 | 6 | fn is_unpin() {} | -------- ----- required by this bound in `is_unpin` ... -39 | is_unpin::(); //~ ERROR E0277 +41 | is_unpin::(); //~ ERROR E0277 | ^^^^^^^^^^^^^^^^^^^^^^ the trait `pin_project::UnsafeUnpin` is not implemented for `NotImplementUnsafUnpin` | = note: required because of the requirements on the impl of `pin_project::UnsafeUnpin` for `pin_project::__private::Wrapper<'_, NotImplementUnsafUnpin>` = note: required because of the requirements on the impl of `std::marker::Unpin` for `NotImplementUnsafUnpin` error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied - --> $DIR/proper_unpin.rs:40:5 + --> $DIR/proper_unpin.rs:43:5 | 6 | fn is_unpin() {} | -------- ----- required by this bound in `is_unpin` ... -40 | is_unpin::>(); //~ ERROR E0277 +43 | is_unpin::>(); //~ ERROR E0277 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | = help: the following implementations were found: @@ -56,12 +56,12 @@ error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` i = note: required because of the requirements on the impl of `std::marker::Unpin` for `OverlappingLifetimeNames<'_, std::marker::PhantomPinned, ()>` error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied - --> $DIR/proper_unpin.rs:41:5 + --> $DIR/proper_unpin.rs:44:5 | 6 | fn is_unpin() {} | -------- ----- required by this bound in `is_unpin` ... -41 | is_unpin::>(); //~ ERROR E0277 +44 | is_unpin::>(); //~ ERROR E0277 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` | = help: the following implementations were found: diff --git a/tests/ui/unstable-features/trivial_bounds-feature-gate.rs b/tests/ui/unstable-features/trivial_bounds-feature-gate.rs index 789ed087..54889557 100644 --- a/tests/ui/unstable-features/trivial_bounds-feature-gate.rs +++ b/tests/ui/unstable-features/trivial_bounds-feature-gate.rs @@ -1,4 +1,4 @@ -// compile-fail +// run-pass // NB: If you change this test, change 'trivial_bounds.rs' at the same time. @@ -7,11 +7,10 @@ use std::marker::PhantomPinned; struct Inner(PhantomPinned); -// As a workaround, you need to use `UnsafeUnpin`. -#[pin_project(UnsafeUnpin)] // Ok +#[pin_project] struct Foo(#[pin] Inner); -#[pin_project] //~ ERROR E0277 +#[pin_project(UnsafeUnpin)] struct Bar(#[pin] Inner); fn main() {} diff --git a/tests/ui/unstable-features/trivial_bounds-feature-gate.stderr b/tests/ui/unstable-features/trivial_bounds-feature-gate.stderr deleted file mode 100644 index 8973216d..00000000 --- a/tests/ui/unstable-features/trivial_bounds-feature-gate.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0277]: the trait bound `std::marker::PhantomPinned: std::marker::Unpin` is not satisfied in `UnpinStructBar` - --> $DIR/trivial_bounds-feature-gate.rs:14:1 - | -14 | #[pin_project] //~ ERROR E0277 - | ^^^^^^^^^^^^^^ within `UnpinStructBar`, the trait `std::marker::Unpin` is not implemented for `std::marker::PhantomPinned` - | - = help: the following implementations were found: - - = note: required because it appears within the type `Inner` - = note: required because it appears within the type `UnpinStructBar` - = help: see issue #48214 - = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/unstable-features/trivial_bounds.rs b/tests/ui/unstable-features/trivial_bounds.rs index 01b6acbb..279fae1d 100644 --- a/tests/ui/unstable-features/trivial_bounds.rs +++ b/tests/ui/unstable-features/trivial_bounds.rs @@ -14,4 +14,7 @@ struct Inner(PhantomPinned); #[pin_project] struct Foo(#[pin] Inner); +#[pin_project(UnsafeUnpin)] +struct Bar(#[pin] Inner); + fn main() {} diff --git a/tests/unsafe_unpin.rs b/tests/unsafe_unpin.rs index 51cd51f9..caa17d24 100644 --- a/tests/unsafe_unpin.rs +++ b/tests/unsafe_unpin.rs @@ -17,12 +17,6 @@ pub struct Blah { #[allow(unsafe_code)] unsafe impl UnsafeUnpin for Blah {} -#[pin_project(UnsafeUnpin)] -pub struct NotImplementUnsafUnpin { - #[pin] - field1: PhantomPinned, -} - #[pin_project(UnsafeUnpin)] pub struct OverlappingLifetimeNames<'_pin, T, U> { #[pin] @@ -40,6 +34,15 @@ fn unsafe_unpin() { is_unpin::>(); } +#[test] +fn trivial_bounds() { + #[pin_project(UnsafeUnpin)] + pub struct NotImplementUnsafUnpin { + #[pin] + field: PhantomPinned, + } +} + #[test] fn test() { let mut x = OverlappingLifetimeNames { field1: 0, field2: 1, field3: &() };