-
-
Notifications
You must be signed in to change notification settings - Fork 34
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>; 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
12 changed files
with
260 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Based on https://stackoverflow.com/a/49250753/1290530 | ||
|
||
use rustc_version::{version_meta, Channel}; | ||
|
||
fn main() { | ||
// Set cfg flags depending on release channel | ||
match version_meta().unwrap().channel { | ||
// Enable our feature on nightly, or when using a | ||
// locally build rustc | ||
Channel::Nightly | Channel::Dev => { | ||
println!("cargo:rustc-cfg=feature=\"RUSTC_IS_NIGHTLY\""); | ||
} | ||
_ => {} | ||
} | ||
} |
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
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 `__UnpinStructFoo<T, U>` | ||
--> $DIR/proper_unpin.rs:22:5 | ||
| | ||
22 | is_unpin::<Foo<T, U>>(); //~ ERROR E0277 | ||
| ^^^^^^^^^^^^^^^^^^^^^ within `__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 `__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`. |
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,11 @@ | ||
use pin_project::pin_project; | ||
|
||
#[pin_project] | ||
struct Foo { | ||
#[pin] | ||
inner: u8 | ||
} | ||
|
||
impl Unpin for __UnpinStructFoo {} | ||
|
||
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,20 @@ | ||
error[E0412]: cannot find type `__UnpinStructFoo` in this scope | ||
--> $DIR/unpin_sneaky.rs:9:16 | ||
| | ||
9 | impl Unpin for __UnpinStructFoo {} | ||
| ^^^^^^^^^^^^^^^^ not found in this scope | ||
help: possible candidate is found in another module, you can import it into scope | ||
| | ||
1 | use crate::__UnpinStructFoo; | ||
| | ||
|
||
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 | ||
| | ||
9 | impl Unpin for __UnpinStructFoo {} | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
Some errors have detailed explanations: E0321, E0412. | ||
For more information about an error, try `rustc --explain E0321`. |