1use crate::fields::{Field, Fields, FieldsNamed, FieldsUnnamed, StructStyle};
9use crate::scope::{Scope, ScopeItem};
10use crate::IdentFormatter;
11use proc_macro2::{Span, TokenStream};
12use quote::{quote, ToTokens, TokenStreamExt};
13use syn::token::{Brace, Colon, Comma, Eq, Paren, Semi};
14use syn::{parse_quote, punctuated::Punctuated, spanned::Spanned};
15use syn::{Attribute, GenericParam, Generics, Ident, ItemImpl, Member, Token, Type, TypePath};
16
17#[derive(Debug)]
19pub struct AnonField {
20 pub attrs: Vec<Attribute>,
22 pub vis: syn::Visibility,
24 pub ident: Option<Ident>,
26 pub colon_token: Option<Colon>,
30 pub ty: Type,
34 pub assignment: Option<(Eq, syn::Expr)>,
36}
37
38#[derive(Debug)]
44pub struct Anon {
45 pub attrs: Vec<Attribute>,
47 pub token: Token![struct],
49 pub generics: Generics,
53 pub style: StructStyle,
55 pub fields: Punctuated<AnonField, Comma>,
57 pub impls: Vec<ItemImpl>,
59}
60
61impl Anon {
62 pub fn into_scope(mut self) -> AnonScope {
64 let mut idfmt = IdentFormatter::new();
65
66 let mut fields = Punctuated::<Field, Comma>::new();
67 let mut field_val_toks = quote! {};
68
69 for (index, pair) in self.fields.into_pairs().enumerate() {
70 let (field, opt_comma) = pair.into_tuple();
71
72 let mut ident = field.ident.clone();
73 let ty = &field.ty;
74 let field_span = match field.assignment {
75 None => quote! { #ty }.span(),
76 Some((ref eq, ref expr)) => quote! { #ty #eq #expr }.span(),
77 };
78 let mem = match self.style {
79 StructStyle::Regular(_) => {
80 let id = ident
81 .unwrap_or_else(|| idfmt.make(format_args!("_field{}", index), field_span));
82 ident = Some(id.clone());
83 Member::Named(id)
84 }
85 StructStyle::Tuple(_, _) => Member::Unnamed(syn::Index {
86 index: index as u32,
87 span: field_span,
88 }),
89 _ => unreachable!(),
90 };
91 let ty_name = match ident {
92 None => format!("_Field{}", index),
93 Some(ref id) => {
94 let ident = id.to_string();
95 let mut buf = "_Field".to_string();
96 buf.reserve(ident.len());
97 let mut next_upper = true;
98 for c in ident.chars() {
99 if c == '_' {
100 next_upper = true;
101 continue;
102 }
103
104 if next_upper {
105 buf.extend(c.to_uppercase());
106 next_upper = false;
107 } else {
108 buf.push(c);
109 }
110 }
111 buf
112 }
113 };
114
115 let ty: Type = match field.ty {
116 Type::ImplTrait(syn::TypeImplTrait { impl_token, bounds }) => {
117 let span = quote! { #impl_token #bounds }.span();
118 let ty = Ident::new(&ty_name, span);
119
120 self.generics.params.push(parse_quote! { #ty: #bounds });
121
122 Type::Path(TypePath {
123 qself: None,
124 path: ty.into(),
125 })
126 }
127 Type::Infer(infer_token) => {
128 let ty = Ident::new(&ty_name, infer_token.span());
129 self.generics.params.push(parse_quote! { #ty });
130
131 Type::Path(TypePath {
132 qself: None,
133 path: ty.into(),
134 })
135 }
136 mut ty => {
137 struct ReplaceInfers<'a> {
138 index: usize,
139 params: Vec<GenericParam>,
140 idfmt: &'a mut IdentFormatter,
141 ty_name: &'a str,
142 }
143 let mut replacer = ReplaceInfers {
144 index: 0,
145 params: vec![],
146 idfmt: &mut idfmt,
147 ty_name: &ty_name,
148 };
149
150 impl<'a> syn::visit_mut::VisitMut for ReplaceInfers<'a> {
151 fn visit_type_mut(&mut self, node: &mut Type) {
152 let (span, bounds) = match node {
153 Type::ImplTrait(syn::TypeImplTrait { impl_token, bounds }) => {
154 (impl_token.span, std::mem::take(bounds))
155 }
156 Type::Infer(infer) => (infer.span(), Punctuated::new()),
157 _ => return,
158 };
159
160 let ident = self
161 .idfmt
162 .make(format_args!("{}{}", self.ty_name, self.index), span);
163 self.index += 1;
164
165 self.params.push(GenericParam::Type(syn::TypeParam {
166 attrs: vec![],
167 ident: ident.clone(),
168 colon_token: Some(Default::default()),
169 bounds,
170 eq_token: None,
171 default: None,
172 }));
173
174 *node = Type::Path(TypePath {
175 qself: None,
176 path: ident.into(),
177 });
178 }
179 }
180 syn::visit_mut::visit_type_mut(&mut replacer, &mut ty);
181
182 self.generics.params.extend(replacer.params);
183 ty
184 }
185 };
186
187 if let Some((_, ref value)) = field.assignment {
188 field_val_toks.append_all(quote! { #mem: #value, });
189 } else {
190 field_val_toks.append_all(quote! { #mem: Default::default(), });
191 }
192
193 fields.push_value(Field {
194 attrs: field.attrs,
195 vis: field.vis,
196 ident,
197 colon_token: field.colon_token.or_else(|| Some(Default::default())),
198 ty,
199 assign: None,
200 });
201 if let Some(comma) = opt_comma {
202 fields.push_punct(comma);
203 }
204 }
205
206 let (fields, semi) = match self.style {
207 StructStyle::Unit(semi) => (Fields::Unit, Some(semi)),
208 StructStyle::Regular(brace_token) => (
209 Fields::Named(FieldsNamed {
210 brace_token,
211 fields,
212 }),
213 None,
214 ),
215 StructStyle::Tuple(paren_token, semi) => (
216 Fields::Unnamed(FieldsUnnamed {
217 paren_token,
218 fields,
219 }),
220 Some(semi),
221 ),
222 };
223
224 let scope = Scope {
225 attrs: self.attrs,
226 vis: syn::Visibility::Inherited,
227 ident: parse_quote! { _Anon },
228 generics: self.generics,
229 item: ScopeItem::Struct {
230 token: self.token,
231 fields,
232 },
233 semi,
234 impls: self.impls,
235 generated: vec![],
236 };
237
238 AnonScope(scope, field_val_toks)
239 }
240}
241
242#[derive(Debug)]
249pub struct AnonScope(Scope, TokenStream);
250
251impl std::ops::Deref for AnonScope {
252 type Target = Scope;
253 fn deref(&self) -> &Scope {
254 &self.0
255 }
256}
257impl std::ops::DerefMut for AnonScope {
258 fn deref_mut(&mut self) -> &mut Scope {
259 &mut self.0
260 }
261}
262
263impl AnonScope {
264 pub fn expand(mut self) -> TokenStream {
270 self.expand_impl_self();
271 self.into_token_stream()
272 }
273}
274
275impl ToTokens for AnonScope {
276 fn to_tokens(&self, tokens: &mut TokenStream) {
277 let scope = &self.0;
278 let field_val_toks = &self.1;
279
280 tokens.append_all(quote! {
281 {
282 #scope
283
284 _Anon {
285 #field_val_toks
286 }
287 }
288 });
289 }
290}
291
292mod parsing {
293 use super::*;
294 use proc_macro_error2::abort;
295 use syn::parse::{Error, Parse, ParseStream, Result};
296 use syn::{braced, parenthesized};
297
298 fn parse_impl(in_ident: Option<&Ident>, input: ParseStream) -> Result<ItemImpl> {
299 let mut attrs = input.call(Attribute::parse_outer)?;
300 let defaultness: Option<Token![default]> = input.parse()?;
301 let unsafety: Option<Token![unsafe]> = input.parse()?;
302 let impl_token: Token![impl] = input.parse()?;
303
304 let has_generics = input.peek(Token![<])
305 && (input.peek2(Token![>])
306 || input.peek2(Token![#])
307 || (input.peek2(Ident) || input.peek2(syn::Lifetime))
308 && (input.peek3(Token![:])
309 || input.peek3(Token![,])
310 || input.peek3(Token![>])
311 || input.peek3(Token![=]))
312 || input.peek2(Token![const]));
313 let mut generics: Generics = if has_generics {
314 input.parse()?
315 } else {
316 Generics::default()
317 };
318
319 let mut first_ty: Type = input.parse()?;
320 let self_ty: Type;
321 let trait_;
322
323 let is_impl_for = input.peek(Token![for]);
324 if is_impl_for {
325 let for_token: Token![for] = input.parse()?;
326 let mut first_ty_ref = &first_ty;
327 while let Type::Group(ty) = first_ty_ref {
328 first_ty_ref = &ty.elem;
329 }
330 if let Type::Path(_) = first_ty_ref {
331 while let Type::Group(ty) = first_ty {
332 first_ty = *ty.elem;
333 }
334 if let Type::Path(TypePath { qself: None, path }) = first_ty {
335 trait_ = Some((None, path, for_token));
336 } else {
337 unreachable!();
338 }
339 } else {
340 return Err(Error::new(for_token.span(), "for without target trait"));
341 }
342 self_ty = input.parse()?;
343 } else {
344 trait_ = None;
345 self_ty = first_ty;
346 }
347
348 generics.where_clause = input.parse()?;
349
350 if self_ty != parse_quote! { Self } {
351 if let Some(ident) = in_ident {
352 if !matches!(self_ty, Type::Path(TypePath {
353 qself: None,
354 path: syn::Path {
355 leading_colon: None,
356 ref segments,
357 }
358 }) if segments.len() == 1 && segments.first().unwrap().ident == *ident)
359 {
360 abort!(
361 self_ty.span(),
362 format!(
363 "expected `Self` or `{0}` or `{0}<...>` or `Trait for Self`, etc",
364 ident
365 )
366 );
367 }
368 } else {
369 abort!(self_ty.span(), "expected `Self` or `Trait for Self`");
370 }
371 }
372
373 let content;
374 let brace_token = braced!(content in input);
375 attrs.extend(Attribute::parse_inner(&content)?);
376
377 let mut items = Vec::new();
378 while !content.is_empty() {
379 items.push(content.parse()?);
380 }
381
382 Ok(ItemImpl {
383 attrs,
384 defaultness,
385 unsafety,
386 impl_token,
387 generics,
388 trait_,
389 self_ty: Box::new(self_ty),
390 brace_token,
391 items,
392 })
393 }
394
395 impl AnonField {
396 fn check_is_fixed(ty: &Type, input_span: Span) -> Result<()> {
397 let is_fixed = match ty {
398 Type::ImplTrait(_) | Type::Infer(_) => false,
399 ty => {
400 struct IsFixed(bool);
401 let mut checker = IsFixed(true);
402
403 impl<'ast> syn::visit::Visit<'ast> for IsFixed {
404 fn visit_type(&mut self, node: &'ast Type) {
405 if matches!(node, Type::ImplTrait(_) | Type::Infer(_)) {
406 self.0 = false;
407 }
408 }
409 }
410 syn::visit::visit_type(&mut checker, ty);
411
412 checker.0
413 }
414 };
415
416 if is_fixed {
417 Ok(())
418 } else {
419 Err(Error::new(
420 input_span,
421 "require either a fixed type or a value assignment",
422 ))
423 }
424 }
425
426 fn parse_named(input: ParseStream) -> Result<Self> {
427 let attrs = input.call(Attribute::parse_outer)?;
428 let vis = input.parse()?;
429
430 let ident = if input.peek(Token![_]) {
431 let _: Token![_] = input.parse()?;
432 None
433 } else {
434 Some(input.parse::<Ident>()?)
435 };
436
437 let mut colon_token = None;
438
439 let ty = if input.peek(Colon) && !input.peek2(Colon) {
441 colon_token = Some(input.parse()?);
442 input.parse()?
443 } else {
444 parse_quote! { _ }
445 };
446
447 let mut assignment = None;
448 if let Ok(eq) = input.parse::<Eq>() {
449 assignment = Some((eq, input.parse()?));
450 } else {
451 Self::check_is_fixed(&ty, input.span())?;
452 }
453
454 Ok(AnonField {
455 attrs,
456 vis,
457 ident,
458 colon_token,
459 ty,
460 assignment,
461 })
462 }
463
464 fn parse_unnamed(input: ParseStream) -> Result<Self> {
465 let attrs = input.call(Attribute::parse_outer)?;
466 let vis = input.parse()?;
467
468 let ty = input.parse()?;
469
470 let mut assignment = None;
471 if let Ok(eq) = input.parse::<Eq>() {
472 assignment = Some((eq, input.parse()?));
473 } else {
474 Self::check_is_fixed(&ty, input.span())?;
475 }
476
477 Ok(AnonField {
478 attrs,
479 vis,
480 ident: None,
481 colon_token: None,
482 ty,
483 assignment,
484 })
485 }
486 }
487
488 impl Parse for Anon {
489 fn parse(input: ParseStream) -> Result<Self> {
490 let attrs = input.call(Attribute::parse_outer)?;
491 let token = input.parse::<Token![struct]>()?;
492
493 let mut generics = input.parse::<Generics>()?;
494
495 let mut lookahead = input.lookahead1();
496 if lookahead.peek(Token![where]) {
497 generics.where_clause = Some(input.parse()?);
498 lookahead = input.lookahead1();
499 }
500
501 let style;
502 let fields;
503 if generics.where_clause.is_none() && lookahead.peek(Paren) {
504 let content;
505 let paren_token = parenthesized!(content in input);
506 fields = content.parse_terminated(AnonField::parse_unnamed, Token![,])?;
507
508 lookahead = input.lookahead1();
509 if lookahead.peek(Token![where]) {
510 generics.where_clause = Some(input.parse()?);
511 lookahead = input.lookahead1();
512 }
513
514 if lookahead.peek(Semi) {
515 style = StructStyle::Tuple(paren_token, input.parse()?);
516 } else {
517 return Err(lookahead.error());
518 }
519 } else if lookahead.peek(Brace) {
520 let content;
521 let brace_token = braced!(content in input);
522 style = StructStyle::Regular(brace_token);
523 fields = content.parse_terminated(AnonField::parse_named, Token![,])?;
524 } else if lookahead.peek(Semi) {
525 style = StructStyle::Unit(input.parse()?);
526 fields = Punctuated::new();
527 } else {
528 return Err(lookahead.error());
529 }
530
531 let mut impls = Vec::new();
532 while !input.is_empty() {
533 impls.push(parse_impl(None, input)?);
534 }
535
536 Ok(Anon {
537 attrs,
538 token,
539 generics,
540 style,
541 fields,
542 impls,
543 })
544 }
545 }
546}