From fafa4e5afa7ba49c4d8b7243f711b1108d81eb9e Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Sat, 17 Apr 2021 00:01:34 +0900 Subject: [PATCH] Preserve `self` as segment of path --- CHANGELOG.md | 2 ++ pin-project-internal/src/utils.rs | 15 +++++++++++++-- tests/pinned_drop.rs | 20 ++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0598f7f..5042cea6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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) diff --git a/pin-project-internal/src/utils.rs b/pin-project-internal/src/utils.rs index 37f35bad..2db00e26 100644 --- a/pin-project-internal/src/utils.rs +++ b/pin-project-internal/src/utils.rs @@ -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); @@ -313,7 +315,6 @@ impl VisitMut for ReplaceReceiver<'_> { // `Self::method` -> `::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); @@ -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`. diff --git a/tests/pinned_drop.rs b/tests/pinned_drop.rs index 9e7287de..785cea3f 100644 --- a/tests/pinned_drop.rs +++ b/tests/pinned_drop.rs @@ -262,3 +262,23 @@ fn inside_macro() { mac!(1); } + +pub mod self_path { + use super::*; + + #[pin_project(PinnedDrop)] + pub struct S(T); + + fn f() {} + + #[pinned_drop] + impl PinnedDrop for self::S { + fn drop(mut self: Pin<&mut Self>) { + self::f(); + let _: self::S<()> = self::S(()); + let _: self::S> = self::S(self.as_mut()); + let self::S(()) = self::S(()); + let self::S(&mut Self(_)) = self::S(&mut *self); + } + } +}