Skip to content

Commit

Permalink
Change 'unsafe_Unpin' to UpperCamelCase (UnsafeUnpin)
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed Aug 11, 2019
1 parent 2f6ef1b commit af2dcc6
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 19 deletions.
2 changes: 1 addition & 1 deletion pin-project-internal/src/pin_project/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl Parse for Args {
let i = input.parse::<Ident>()?;
match &*i.to_string() {
"PinnedDrop" => pinned_drop = Some(i.span()),
"unsafe_Unpin" => unsafe_unpin = Some(i.span()),
"UnsafeUnpin" => unsafe_unpin = Some(i.span()),
_ => return Err(error!(i, "an invalid argument was passed")),
}
}
Expand Down
32 changes: 16 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ pub use pin_project_internal::project;
/// To enforce this, this attribute will automatically generate an `Unpin` implementation
/// for you, which will require that all structurally pinned fields be `Unpin`
/// If you wish to provide an manual `Unpin` impl, you can do so via the
/// `unsafe_Unpin` argument.
/// `UnsafeUnpin` argument.
///
/// 2. The destructor of the struct must not move structural fields out of its argument.
///
Expand Down Expand Up @@ -300,14 +300,14 @@ pub use pin_project_internal::project;
/// ```
///
/// If you want to implement [`Unpin`] manually,
/// you must use the `unsafe_Unpin` argument to
/// you must use the `UnsafeUnpin` argument to
/// `#[pin_project]`.
///
/// ```rust
/// use pin_project::{pin_project, UnsafeUnpin};
/// use std::pin::Pin;
///
/// #[pin_project(unsafe_Unpin)]
/// #[pin_project(UnsafeUnpin)]
/// struct Foo<T, U> {
/// #[pin]
/// future: T,
Expand Down Expand Up @@ -509,7 +509,7 @@ pub use pin_project_internal::pin_project;
pub use pin_project_internal::pinned_drop;

/// A trait used for custom implementations of [`Unpin`].
/// This trait is used in conjunction with the `unsafe_Unpin`
/// This trait is used in conjunction with the `UnsafeUnpin`
/// argument to [`pin_project`]
///
/// The Rust [`Unpin`] trait is safe to implement - by itself,
Expand All @@ -532,10 +532,10 @@ pub use pin_project_internal::pinned_drop;
/// this crate will generate an `Unpin` impl for your type that 'forwards' to
/// your `UnsafeUnpin` impl. However, this trait is `unsafe` - since your type
/// uses structural pinning (otherwise, you wouldn't be using this crate!),
/// you must be sure that your `UnsafeUnpinned` impls follows all of
/// you must be sure that your `UnsafeUnpin` impls follows all of
/// the requirements for an `Unpin` impl of a structurally-pinned type.
///
/// Note that if you specify `#[pin_project(unsafe_Unpin)]`, but do *not*
/// Note that if you specify `#[pin_project(UnsafeUnpin)]`, but do *not*
/// provide an impl of `UnsafeUnpin`, your type will never implement `Unpin`.
/// This is effectly the same thing as adding a `PhantomUnpin` to your type
///
Expand All @@ -550,7 +550,7 @@ pub use pin_project_internal::pinned_drop;
/// ```rust
/// use pin_project::{pin_project, UnsafeUnpin};
///
/// #[pin_project(unsafe_Unpin)]
/// #[pin_project(UnsafeUnpin)]
/// struct Foo<K, V> {
/// #[pin]
/// field_1: K,
Expand Down Expand Up @@ -586,47 +586,47 @@ pub mod __private {

// This is an internal helper struct used by `pin-project-internal`.
// This allows us to force an error if the user tries to provide
// a regular `Unpin` impl when they specify the `unsafe_Unpin` argument.
// a regular `Unpin` impl when they specify the `UnsafeUnpin` argument.
// This is why we need Wrapper:
//
// Supposed we have the following code:
//
// #[pin_project(unsafe_Unpin)]
// #[pin_project(UnsafeUnpin)]
// struct MyStruct<T> {
// #[pin] field: T
// }
//
// impl<T> Unpin for MyStruct<T> where MyStruct<T>: UnsafeUnpinned {} // generated by pin-project-internal
// impl<T> Unpin for MyStruct<T> where MyStruct<T>: UnsafeUnpin {} // generated by pin-project-internal
// impl<T> Unpin for MyStruct<T> where T: Copy // written by the user
//
// We want this code to be rejected - the user is completely bypassing unsafe_Unpin,
// We want this code to be rejected - the user is completely bypassing `UnsafeUnpin`,
// and providing an unsound Unpin impl in safe code!
//
// Unfortunately, the Rust compiler will accept the above code.
// Because MyStruct is declared in the same crate as the user-provided impl,
// the compiler will notice that 'MyStruct<T>: UnsafeUnpinned' never holds.
// the compiler will notice that 'MyStruct<T>: UnsafeUnpin' never holds.
//
// The solution is to introduce the 'Wrapper' struct, which is defined
// in the 'pin-project' crate.
//
// We now have code that looks like this:
//
// impl<T> Unpin for MyStruct<T> where Wrapper<MyStruct<T>>: UnsafeUnpinned {} // generated by pin-project-internal
// impl<T> Unpin for MyStruct<T> where Wrapper<MyStruct<T>>: UnsafeUnpin {} // generated by pin-project-internal
// impl<T> Unpin for MyStruct<T> where T: Copy // written by the user
//
// We also have 'unsafe impl<T> UnsafeUnpin for Wrapper<T> where T: UnsafeUnpin {}' in the
// 'pin-project' crate.
//
// Now, our generated impl has a bound involving a type defined in another crate - Wrapper.
// This will cause rust to conservatively assume that 'Wrapper<MyStruct<T>>: UnsafeUnpinned'
// This will cause rust to conservatively assume that 'Wrapper<MyStruct<T>>: UnsafeUnpin'
// holds, in the interest of preserving forwards compatibility (in case such an impl is added
// for Wrapper<T> in a new version of the crate).
//
// This will cause rust to reject any other Unpin impls for MyStruct<T>, since it will
// assume that our generated impl could potentially apply in any situation.
//
// This acheives the desired effect - when the user writes `#[pin_project(unsafe_Unpin)]`,
// the user must either provide no impl of `UnsafeUnpinned` (which is equivalent
// This acheives the desired effect - when the user writes `#[pin_project(UnsafeUnpin)]`,
// the user must either provide no impl of `UnsafeUnpin` (which is equivalent
// to making the type never implement Unpin), or provide an impl of `UnsafeUnpin`.
// It is impossible for them to provide an impl of `Unpin`
#[doc(hidden)]
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/pin_project/forget-unsafe-unpin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use pin_project::pin_project;
// FIXME
#[test]
fn unsafe_unpin() {
#[pin_project(unsafe_Unpin)]
#[pin_project(UnsafeUnpin)]
pub struct Blah<T> {
field_1: u8,
#[pin]
Expand Down
2 changes: 1 addition & 1 deletion tests/unsafe_unpin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use pin_project::{pin_project, UnsafeUnpin};

#[test]
fn unsafe_unpin() {
#[pin_project(unsafe_Unpin)]
#[pin_project(UnsafeUnpin)]
pub struct Blah<T> {
field_1: u8,
#[pin]
Expand Down

0 comments on commit af2dcc6

Please sign in to comment.