Skip to content

Commit

Permalink
Merge #94 #96
Browse files Browse the repository at this point in the history
94: Remove "project_attr" feature and always enable #[project] attribute r=taiki-e a=taiki-e

Closes #82

96: Determine the visibility based on the original type r=taiki-e a=taiki-e

The visibility of the projected type and projection method is based on the original type. However, if the visibility of the original type is `pub`, the visibility of the projected type and the projection method is `pub(crate)`.

Closes #81


Co-authored-by: Taiki Endo <[email protected]>
  • Loading branch information
bors[bot] and taiki-e authored Sep 19, 2019
3 parents b6d8141 + 3462ea4 + 65944b8 commit 68e783d
Show file tree
Hide file tree
Showing 13 changed files with 112 additions and 56 deletions.
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ all-features = true
members = ["pin-project-internal"]

[features]
# Enable to use `project` attribute.
project_attr = ["pin-project-internal/project_attr"]
# Enable to allow using this crate as a renamed dependency
renamed = ["pin-project-internal/renamed"]

Expand Down
6 changes: 4 additions & 2 deletions examples/pinned_drop-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,15 @@ pub struct Foo<'a, T> {

#[allow(clippy::mut_mut)]
#[allow(dead_code)]
struct __FooProjection<'_pin, 'a, T> {
pub(crate) struct __FooProjection<'_pin, 'a, T> {
was_dropped: &'_pin mut &'a mut bool,
field: ::core::pin::Pin<&'_pin mut T>,
}

impl<'a, T> Foo<'a, T> {
fn project<'_pin>(self: ::core::pin::Pin<&'_pin mut Self>) -> __FooProjection<'_pin, '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 {
Expand Down
6 changes: 4 additions & 2 deletions examples/unsafe_unpin-expanded.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,15 @@ pub struct Foo<T, U> {

#[allow(clippy::mut_mut)]
#[allow(dead_code)]
struct __FooProjection<'_pin, T, U> {
pub(crate) struct __FooProjection<'_pin, T, U> {
pinned: ::core::pin::Pin<&'_pin mut T>,
unpinned: &'_pin mut U,
}

impl<T, U> Foo<T, U> {
fn project<'_pin>(self: ::core::pin::Pin<&'_pin mut Self>) -> __FooProjection<'_pin, T, U> {
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: unpinned }
Expand Down
4 changes: 1 addition & 3 deletions pin-project-internal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,13 @@ all-features = true
proc-macro = true

[features]
# Enable to use `project` attribute.
project_attr = ["syn/visit-mut"]
# Enable to allow using the crate with a renamed 'pin-project' dependency
renamed = ["proc-macro-crate", "serde", "lazy_static"]

[dependencies]
proc-macro2 = "1.0"
quote = "1.0"
syn = { version = "1.0", features = ["full"] }
syn = { version = "1.0", features = ["full", "visit-mut"] }

proc-macro-crate = { version = "0.1.4", optional = true }
# Required until a new toml-rs release is made with https://github.com/alexcrichton/toml-rs/pull/311,
Expand Down
20 changes: 6 additions & 14 deletions pin-project-internal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ mod utils;

mod pin_project;
mod pinned_drop;
#[cfg(feature = "project_attr")]
mod project;

use proc_macro::TokenStream;
Expand All @@ -45,6 +44,10 @@ use syn::parse::Nothing;
/// # }
/// ```
///
/// The visibility of the projected type and projection method is based on the
/// original type. However, if the visibility of the original type is `pub`,
/// the visibility of the projected type and the projection method is `pub(crate)`.
///
/// If you want to call the `project` method multiple times or later use the
/// original Pin type, it needs to use [`.as_mut()`][`Pin::as_mut`] to avoid
/// consuming the `Pin`.
Expand Down Expand Up @@ -265,30 +268,23 @@ use syn::parse::Nothing;
///
/// ### Enums
///
/// `pin_project` also supports enums, but to use it ergonomically, you need
/// to use the [`project`] attribute.
///
/// *This attribute is only available if pin-project is built
/// with the `"project_attr"` feature.*
/// `pin_project` also supports enums, but to use it, you need to use with the
/// [`project`] attribute.
///
/// The attribute at the expression position is not stable, so you need to use
/// a dummy `#[project]` attribute for the function.
///
/// ```rust
/// # #[cfg(feature = "project_attr")]
/// use pin_project::{project, pin_project};
/// # #[cfg(feature = "project_attr")]
/// use std::pin::Pin;
///
/// # #[cfg(feature = "project_attr")]
/// #[pin_project]
/// enum Foo<A, B, C> {
/// Tuple(#[pin] A, B),
/// Struct { field: C },
/// Unit,
/// }
///
/// # #[cfg(feature = "project_attr")]
/// impl<A, B, C> Foo<A, B, C> {
/// #[project] // Nightly does not need a dummy attribute to the function.
/// fn baz(self: Pin<&mut Self>) {
Expand Down Expand Up @@ -368,9 +364,6 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
// TODO: Move this doc into pin-project crate when https://github.com/rust-lang/rust/pull/62855 merged.
/// An attribute to provide way to refer to the projected type.
///
/// *This attribute is available if pin-project is built with the
/// `"project_attr"` feature.*
///
/// The following three syntaxes are supported.
///
/// ## `impl` blocks
Expand Down Expand Up @@ -479,7 +472,6 @@ pub fn pinned_drop(args: TokenStream, input: TokenStream) -> TokenStream {
/// }
/// }
/// ```
#[cfg(feature = "project_attr")]
#[proc_macro_attribute]
pub fn project(args: TokenStream, input: TokenStream) -> TokenStream {
let _: Nothing = syn::parse_macro_input!(args);
Expand Down
36 changes: 21 additions & 15 deletions pin-project-internal/src/pin_project/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ use syn::{
};

use crate::utils::{
self, collect_cfg, crate_path, proj_ident, proj_lifetime_name, VecExt, DEFAULT_LIFETIME_NAME,
self, collect_cfg, crate_path, determine_visibility, proj_ident, proj_lifetime_name, VecExt,
DEFAULT_LIFETIME_NAME,
};

use super::PIN;
Expand All @@ -16,15 +17,15 @@ pub(super) fn parse_attribute(args: TokenStream, mut item: Item) -> Result<Token
let cx;
let proj_items = match &mut item {
Item::Struct(item) => {
cx = Context::new(args, &mut item.attrs, &item.ident, &item.generics)?;
cx = Context::new(args, &mut item.attrs, &item.ident, &item.vis, &item.generics)?;

let packed_check = ensure_not_packed(&item)?;
let mut proj_items = cx.parse_struct(item)?;
proj_items.extend(packed_check);
proj_items
}
Item::Enum(item) => {
cx = Context::new(args, &mut item.attrs, &item.ident, &item.generics)?;
cx = Context::new(args, &mut item.attrs, &item.ident, &item.vis, &item.generics)?;

// We don't need to check for '#[repr(packed)]',
// since it does not apply to enums.
Expand Down Expand Up @@ -96,6 +97,9 @@ struct Context {
/// Name of the projected type.
proj_ident: Ident,

/// Visibility of the original type.
vis: Visibility,

/// Generics of the original type.
generics: Generics,

Expand All @@ -114,6 +118,7 @@ impl Context {
args: TokenStream,
attrs: &mut Vec<Attribute>,
orig_ident: &Ident,
vis: &Visibility,
generics: &Generics,
) -> Result<Self> {
let Args { pinned_drop, unsafe_unpin } = syn::parse2(args)?;
Expand All @@ -133,6 +138,7 @@ impl Context {
crate_path,
orig_ident: orig_ident.clone(),
proj_ident: proj_ident(orig_ident),
vis: determine_visibility(vis),
generics: generics.clone(),
lifetime,
unsafe_unpin,
Expand Down Expand Up @@ -258,7 +264,7 @@ impl Context {

/// Creates an implementation of the projection method.
fn make_proj_impl(&self, proj_body: &TokenStream) -> TokenStream {
let Context { proj_ident, orig_ident, lifetime, .. } = &self;
let Context { proj_ident, orig_ident, vis, lifetime, .. } = self;

let proj_generics = self.proj_generics();
let proj_ty_generics = proj_generics.split_for_impl().1;
Expand All @@ -267,7 +273,7 @@ impl Context {

quote! {
impl #impl_generics #orig_ident #ty_generics #where_clause {
fn project<#lifetime>(
#vis fn project<#lifetime>(
self: ::core::pin::Pin<&#lifetime mut Self>,
) -> #proj_ident #proj_ty_generics {
unsafe {
Expand Down Expand Up @@ -385,14 +391,14 @@ impl Context {
Fields::Unit => unreachable!(),
};

let Context { orig_ident, proj_ident, .. } = &self;
let Context { orig_ident, proj_ident, vis, .. } = self;
let proj_generics = self.proj_generics();
let where_clause = item.generics.split_for_impl().2;

let mut proj_items = quote! {
#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
#[allow(dead_code)] // This lint warns unused fields/variants.
struct #proj_ident #proj_generics #where_clause #proj_fields
#vis struct #proj_ident #proj_generics #where_clause #proj_fields
};

let proj_body = quote! {
Expand All @@ -410,14 +416,14 @@ impl Context {

let (proj_variants, proj_arms) = self.visit_variants(item)?;

let proj_ident = &self.proj_ident;
let Context { proj_ident, vis, .. } = &self;
let proj_generics = self.proj_generics();
let where_clause = item.generics.split_for_impl().2;

let mut proj_items = quote! {
#[allow(clippy::mut_mut)] // This lint warns `&mut &mut <ty>`.
#[allow(dead_code)] // This lint warns unused fields/variants.
enum #proj_ident #proj_generics #where_clause {
#vis enum #proj_ident #proj_generics #where_clause {
#(#proj_variants,)*
}
};
Expand Down Expand Up @@ -466,13 +472,13 @@ impl Context {
let mut proj_pat = Vec::with_capacity(fields.len());
let mut proj_body = Vec::with_capacity(fields.len());
let mut proj_fields = Vec::with_capacity(fields.len());
for Field { attrs, ident, ty, .. } in fields {
for Field { attrs, vis, ident, ty, .. } in fields {
let cfg = collect_cfg(attrs);
if self.find_pin_attr(attrs)? {
let lifetime = &self.lifetime;
proj_fields.push(quote! {
#(#cfg)*
#ident: ::core::pin::Pin<&#lifetime mut #ty>
#vis #ident: ::core::pin::Pin<&#lifetime mut #ty>
});
proj_body.push(quote! {
#(#cfg)*
Expand All @@ -482,7 +488,7 @@ impl Context {
let lifetime = &self.lifetime;
proj_fields.push(quote! {
#(#cfg)*
#ident: &#lifetime mut #ty
#vis #ident: &#lifetime mut #ty
});
proj_body.push(quote! {
#(#cfg)*
Expand All @@ -508,7 +514,7 @@ impl Context {
let mut proj_pat = Vec::with_capacity(fields.len());
let mut proj_body = Vec::with_capacity(fields.len());
let mut proj_fields = Vec::with_capacity(fields.len());
for (i, Field { attrs, ty, .. }) in fields.iter_mut().enumerate() {
for (i, Field { attrs, vis, ty, .. }) in fields.iter_mut().enumerate() {
let id = format_ident!("_x{}", i);
let cfg = collect_cfg(attrs);
if !cfg.is_empty() {
Expand All @@ -521,15 +527,15 @@ impl Context {
if self.find_pin_attr(attrs)? {
let lifetime = &self.lifetime;
proj_fields.push(quote! {
::core::pin::Pin<&#lifetime mut #ty>
#vis ::core::pin::Pin<&#lifetime mut #ty>
});
proj_body.push(quote! {
::core::pin::Pin::new_unchecked(#id)
});
} else {
let lifetime = &self.lifetime;
proj_fields.push(quote! {
&#lifetime mut #ty
#vis &#lifetime mut #ty
});
proj_body.push(quote! {
#id
Expand Down
16 changes: 14 additions & 2 deletions pin-project-internal/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use quote::format_ident;
use quote::{format_ident, quote_spanned};
use syn::{
punctuated::Punctuated,
token::{self, Comma},
Expand All @@ -12,7 +12,7 @@ pub(crate) fn proj_ident(ident: &Ident) -> Ident {
format_ident!("__{}Projection", ident)
}

/// Determine the lifetime names. Ensure it doesn't overlap with any existing lifetime names.
/// Determines the lifetime names. Ensure it doesn't overlap with any existing lifetime names.
pub(crate) fn proj_lifetime_name(
lifetime_name: &mut String,
generics: &Punctuated<GenericParam, Comma>,
Expand Down Expand Up @@ -52,6 +52,18 @@ pub(crate) fn proj_generics(generics: &mut Generics, lifetime: Lifetime) {
);
}

/// Determines the visibility of the projected type and projection method.
pub(crate) fn determine_visibility(vis: &Visibility) -> Visibility {
if let Visibility::Public(token) = vis {
syn::parse2(quote_spanned! { token.pub_token.span =>
pub(crate)
})
.unwrap()
} else {
vis.clone()
}
}

pub(crate) fn collect_cfg(attrs: &[Attribute]) -> Vec<Attribute> {
attrs.iter().filter(|attr| attr.path.is_ident("cfg")).cloned().collect()
}
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ pub use pin_project_internal::pin_project;
#[doc(hidden)]
pub use pin_project_internal::pinned_drop;

#[cfg(feature = "project_attr")]
#[doc(hidden)]
pub use pin_project_internal::project;

Expand Down
1 change: 0 additions & 1 deletion tests/compiletest.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![cfg(compiletest)]
#![cfg(pin_project_show_unpin_struct)]
#![cfg(feature = "project_attr")]
#![warn(rust_2018_idioms, single_use_lifetimes)]

use std::{env, path::PathBuf};
Expand Down
29 changes: 16 additions & 13 deletions tests/pin_project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,10 +240,6 @@ fn combine() {
unsafe impl<T: Unpin> UnsafeUnpin for Foo<T> {}
}

// This 'allow' is unrelated to the code
// generated by pin-project - it's just to
// allow us to put a private enum in a public enum
#[allow(private_in_public)]
#[test]
fn private_type_in_public_type() {
#[pin_project]
Expand All @@ -253,15 +249,6 @@ fn private_type_in_public_type() {
}

struct PrivateStruct<T>(T);

#[pin_project]
pub enum PublicEnum {
Variant(#[pin] PrivateEnum),
}

enum PrivateEnum {
OtherVariant(u8),
}
}

#[test]
Expand Down Expand Up @@ -320,3 +307,19 @@ fn lifetime_project() {
}
}
}

mod visibility {
use pin_project::pin_project;

#[pin_project]
pub(crate) struct A {
pub b: u8,
}
}

#[test]
fn visibility() {
let mut x = visibility::A { b: 0 };
let x = Pin::new(&mut x).project();
let _: &mut u8 = x.b;
}
1 change: 0 additions & 1 deletion tests/project.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#![cfg(feature = "project_attr")]
#![warn(unsafe_code)]
#![warn(rust_2018_idioms, single_use_lifetimes)]
#![allow(dead_code)]
Expand Down
Loading

0 comments on commit 68e783d

Please sign in to comment.