forked from taiki-e/pin-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow using #[pin_project] type with private field types
Previously, given code such as: ```rust struct Private<T>; \#[pin_project] pub struct Public<T> { #[pin] private: Private<T> } ``` we would generate an Unpin impl like this: ```rust impl Unpin for Public where Private: Unpin {} ``` Unfortunately, since Private is not a public type, this would cause an E0446 ('private type `Private` in public interface) When RFC 2145 is implemented (rust-lang/rust#48054), this will become a lint, rather then a hard error. In the time being, we need a solution that will work with the current type privacy rules. The solution is to generate code like this: ```rust fn __private_scope() { pub struct __UnpinPublic<T> { __field0: Private<T> } impl<T> Unpin for Public<T> where __UnpinPublic<T>: Unpin {} } ``` That is, we generate a new struct, containing all of the pinned fields from our #[pin_project] type. This struct is delcared within a function, which makes it impossible to be named by user code. This guarnatees 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', satisfiying 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.
- Loading branch information
Showing
6 changed files
with
144 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// compile-fail | ||
|
||
#![deny(warnings, unsafe_code)] | ||
|
||
use pin_project::{pin_project, pinned_drop}; | ||
use std::pin::Pin; | ||
|
||
struct Inner<T> { | ||
val: T | ||
} | ||
|
||
#[pin_project] | ||
struct Foo<T, U> { | ||
#[pin] | ||
inner: Inner<T>, | ||
other: U | ||
} | ||
|
||
fn is_unpin<T: Unpin>() {} | ||
|
||
fn bar<T, U>() { | ||
is_unpin::<Foo<T, U>>(); //~ ERROR E0277 | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
error[E0277]: the trait bound `T: std::marker::Unpin` is not satisfied in `__unpin_scope_Foo::__UnpinStructFoo<T, U>` | ||
--> $DIR/proper_unpin.rs:22:5 | ||
| | ||
22 | is_unpin::<Foo<T, U>>(); //~ ERROR E0277 | ||
| ^^^^^^^^^^^^^^^^^^^^^ within `__unpin_scope_Foo::__UnpinStructFoo<T, U>`, the trait `std::marker::Unpin` is not implemented for `T` | ||
| | ||
= help: consider adding a `where T: std::marker::Unpin` bound | ||
= note: required because it appears within the type `Inner<T>` | ||
= note: required because it appears within the type `__unpin_scope_Foo::__UnpinStructFoo<T, U>` | ||
= note: required because of the requirements on the impl of `std::marker::Unpin` for `Foo<T, U>` | ||
note: required by `is_unpin` | ||
--> $DIR/proper_unpin.rs:19:1 | ||
| | ||
19 | fn is_unpin<T: Unpin>() {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0277`. |