Skip to content

Commit fd42c9b

Browse files
committed
Perform Self replacement
1 parent 378533b commit fd42c9b

2 files changed

Lines changed: 65 additions & 3 deletions

File tree

pin-init-internal/src/pin_init.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::convert::TryFrom;
33
use proc_macro2::{Span, TokenStream};
44
use quote::{format_ident, quote, quote_spanned};
55
use syn::parse::{discouraged::Speculative, Parse, ParseStream};
6+
use syn::visit_mut::VisitMut;
67
use syn::GenericArgument;
78
use syn::{
89
braced, punctuated::Punctuated, token::Brace, Data, DeriveInput, Error, Expr, ExprPath, Fields,
@@ -22,6 +23,23 @@ pub fn pin_init_attr(_attr: TokenStream, input: TokenStream) -> Result<TokenStre
2223
})
2324
}
2425

26+
struct SelfReplacer<'a> {
27+
segment: &'a syn::PathSegment,
28+
}
29+
30+
impl VisitMut for SelfReplacer<'_> {
31+
// Don't recurse into items because meaning of `Self` is different there.
32+
fn visit_item_mut(&mut self, _: &mut syn::Item) {}
33+
34+
fn visit_path_segment_mut(&mut self, seg: &mut syn::PathSegment) {
35+
if seg.ident == "Self" {
36+
*seg = self.segment.clone();
37+
return;
38+
}
39+
syn::visit_mut::visit_path_segment_mut(self, seg);
40+
}
41+
}
42+
2543
pub fn pin_init_derive(input: TokenStream) -> Result<TokenStream> {
2644
let DeriveInput {
2745
vis,
@@ -32,7 +50,7 @@ pub fn pin_init_derive(input: TokenStream) -> Result<TokenStream> {
3250
} = syn::parse2(input)?;
3351

3452
// Check this is a struct, and extract inner.
35-
let data = match data {
53+
let mut data = match data {
3654
Data::Struct(v) => v,
3755
Data::Enum(v) => {
3856
return Err(Error::new(
@@ -65,6 +83,21 @@ pub fn pin_init_derive(input: TokenStream) -> Result<TokenStream> {
6583
})
6684
.collect();
6785

86+
let self_path = syn::PathSegment {
87+
ident: ident.clone(),
88+
arguments: syn::PathArguments::AngleBracketed(syn::AngleBracketedGenericArguments {
89+
colon2_token: Some(Default::default()),
90+
lt_token: Default::default(),
91+
args: ty_generics.iter().cloned().collect(),
92+
gt_token: Default::default(),
93+
}),
94+
};
95+
96+
SelfReplacer {
97+
segment: &self_path,
98+
}
99+
.visit_data_struct_mut(&mut data);
100+
68101
let (mut fields, named) = match data.fields {
69102
Fields::Named(v) => (v.named, true),
70103
Fields::Unnamed(v) => (v.unnamed, false),
@@ -194,7 +227,7 @@ pub fn pin_init_derive(input: TokenStream) -> Result<TokenStream> {
194227
#(,#generics)*
195228
#typestate_impl
196229
> #where_clause {
197-
ptr: ::pin_init::PinUninit<#this_lifetime, #ident<#(#ty_generics),*>>,
230+
ptr: ::pin_init::PinUninit<#this_lifetime, #self_path>,
198231
}
199232

200233
#[allow(nonstandard_style)]
@@ -348,7 +381,7 @@ pub fn pin_init_derive(input: TokenStream) -> Result<TokenStream> {
348381
impl<
349382
#this_lifetime
350383
#(,#generics)*
351-
> ::pin_init::Initable<#this_lifetime> for #ident<#(#ty_generics),*> #where_clause {
384+
> ::pin_init::Initable<#this_lifetime> for #self_path #where_clause {
352385
#[doc(hidden)]
353386
type __PinInitBuilder = #builder_ident <
354387
#this_lifetime

tests/complex.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,32 @@ where
5050
struct Unsized<T: ?Sized> {
5151
t: T,
5252
}
53+
54+
#[pin_init]
55+
struct Tree {
56+
left: Option<Box<Self>>,
57+
right: Option<Box<Self>>,
58+
}
59+
60+
#[pin_init]
61+
struct Tree2 where Self: {
62+
left: Option<Box<Self>>,
63+
right: Option<Box<Self>>,
64+
}
65+
66+
#[pin_init]
67+
struct Tree3 {
68+
left: Option<Box<Self>>,
69+
right: Option<Box<Self>>,
70+
phantom: [(); {
71+
struct Foo;
72+
73+
impl Foo {
74+
fn new() -> Self {
75+
Foo
76+
}
77+
}
78+
79+
0
80+
}]
81+
}

0 commit comments

Comments
 (0)