Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preserve self as segment of path #326

Merged
merged 1 commit into from
Apr 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ Note: In this file, do not use the hard wrap in the middle of a sentence for com

## [Unreleased]

- Fix compile error when using `self::` as prefix of path inside `#[pinned_drop]` impl.

## [1.0.6] - 2021-03-25

- [Suppress `clippy::semicolon_if_nothing_returned` lint in generated code.](https://github.com/taiki-e/pin-project/pull/318)
Expand Down
15 changes: 13 additions & 2 deletions pin-project-internal/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,9 @@ impl<'a> ParseBufferExt<'a> for ParseBuffer<'a> {
// visitors

// Replace `self`/`Self` with `__self`/`self_ty`.
// Based on https://github.com/dtolnay/async-trait/blob/0.1.35/src/receiver.rs
// Based on:
// - https://github.com/dtolnay/async-trait/blob/0.1.35/src/receiver.rs
// - https://github.com/dtolnay/async-trait/commit/6029cbf375c562ca98fa5748e9d950a8ff93b0e7

pub(crate) struct ReplaceReceiver<'a>(pub(crate) &'a TypePath);

Expand Down Expand Up @@ -313,7 +315,6 @@ impl VisitMut for ReplaceReceiver<'_> {
// `Self::method` -> `<Receiver>::method`
fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
if expr.qself.is_none() {
prepend_underscore_to_self(&mut expr.path.segments[0].ident);
self.self_to_qself(&mut expr.qself, &mut expr.path);
}
visit_mut::visit_expr_path_mut(self, expr);
Expand Down Expand Up @@ -341,6 +342,16 @@ impl VisitMut for ReplaceReceiver<'_> {
visit_mut::visit_pat_tuple_struct_mut(self, pat);
}

fn visit_path_mut(&mut self, path: &mut Path) {
if path.segments.len() == 1 {
// Replace `self`, but not `self::function`.
prepend_underscore_to_self(&mut path.segments[0].ident);
}
for segment in &mut path.segments {
self.visit_path_arguments_mut(&mut segment.arguments);
}
}

fn visit_item_mut(&mut self, item: &mut Item) {
match item {
// Visit `macro_rules!` because locally defined macros can refer to `self`.
Expand Down
20 changes: 20 additions & 0 deletions tests/pinned_drop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,23 @@ fn inside_macro() {

mac!(1);
}

pub mod self_path {
use super::*;

#[pin_project(PinnedDrop)]
pub struct S<T: Unpin>(T);

fn f() {}

#[pinned_drop]
impl<T: Unpin> PinnedDrop for self::S<T> {
fn drop(mut self: Pin<&mut Self>) {
self::f();
let _: self::S<()> = self::S(());
let _: self::S<Pin<&mut Self>> = self::S(self.as_mut());
let self::S(()) = self::S(());
let self::S(&mut Self(_)) = self::S(&mut *self);
}
}
}