1use crate::fields::{Field, Fields, FieldsNamed, FieldsUnnamed, StructStyle};
9use crate::scope::{Scope, ScopeItem};
10use crate::{IdentFormatter, error_on_attrs};
11use proc_macro2::{Span, TokenStream};
12use quote::{ToTokens, TokenStreamExt, quote};
13use syn::token::{Brace, Colon, Comma, Eq, Paren, Semi};
14use syn::{Attribute, GenericParam, Generics, Ident, ItemImpl, Member, Token, Type, TypePath};
15use syn::{parse_quote, punctuated::Punctuated, spanned::Spanned};
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 {
117 attrs,
118 impl_token,
119 bounds,
120 }) => {
121 error_on_attrs(&attrs);
122
123 let span = quote! { #impl_token #bounds }.span();
124 let ty = Ident::new(&ty_name, span);
125
126 self.generics.params.push(parse_quote! { #ty: #bounds });
127
128 Type::Path(TypePath {
129 attrs: vec![],
130 qself: None,
131 path: ty.into(),
132 })
133 }
134 Type::Infer(infer_token) => {
135 let ty = Ident::new(&ty_name, infer_token.span());
136 self.generics.params.push(parse_quote! { #ty });
137
138 Type::Path(TypePath {
139 attrs: vec![],
140 qself: None,
141 path: ty.into(),
142 })
143 }
144 mut ty => {
145 struct ReplaceInfers<'a> {
146 index: usize,
147 params: Vec<GenericParam>,
148 idfmt: &'a mut IdentFormatter,
149 ty_name: &'a str,
150 }
151 let mut replacer = ReplaceInfers {
152 index: 0,
153 params: vec![],
154 idfmt: &mut idfmt,
155 ty_name: &ty_name,
156 };
157
158 impl<'a> syn::visit_mut::VisitMut for ReplaceInfers<'a> {
159 fn visit_type_mut(&mut self, node: &mut Type) {
160 let (span, bounds) = match node {
161 Type::ImplTrait(syn::TypeImplTrait {
162 attrs,
163 impl_token,
164 bounds,
165 }) => {
166 error_on_attrs(attrs);
167 (impl_token.span, std::mem::take(bounds))
168 }
169 Type::Infer(infer) => (infer.span(), Punctuated::new()),
170 _ => return,
171 };
172
173 let ident = self
174 .idfmt
175 .make(format_args!("{}{}", self.ty_name, self.index), span);
176 self.index += 1;
177
178 self.params.push(GenericParam::Type(syn::TypeParam {
179 attrs: vec![],
180 ident: ident.clone(),
181 colon_token: Some(Default::default()),
182 bounds,
183 default: None,
184 }));
185
186 *node = Type::Path(TypePath {
187 attrs: vec![],
188 qself: None,
189 path: ident.into(),
190 });
191 }
192 }
193 syn::visit_mut::visit_type_mut(&mut replacer, &mut ty);
194
195 self.generics.params.extend(replacer.params);
196 ty
197 }
198 };
199
200 if let Some((_, ref value)) = field.assignment {
201 field_val_toks.append_all(quote! { #mem: #value, });
202 } else {
203 field_val_toks.append_all(quote! { #mem: Default::default(), });
204 }
205
206 fields.push_value(Field {
207 attrs: field.attrs,
208 vis: field.vis,
209 ident,
210 colon_token: field.colon_token.or_else(|| Some(Default::default())),
211 ty,
212 assign: None,
213 });
214 if let Some(comma) = opt_comma {
215 fields.push_punct(comma);
216 }
217 }
218
219 let (fields, semi) = match self.style {
220 StructStyle::Unit(semi) => (Fields::Unit, Some(semi)),
221 StructStyle::Regular(brace_token) => (
222 Fields::Named(FieldsNamed {
223 brace_token,
224 fields,
225 }),
226 None,
227 ),
228 StructStyle::Tuple(paren_token, semi) => (
229 Fields::Unnamed(FieldsUnnamed {
230 paren_token,
231 fields,
232 }),
233 Some(semi),
234 ),
235 };
236
237 let scope = Scope {
238 attrs: self.attrs,
239 vis: syn::Visibility::Inherited,
240 ident: parse_quote! { _Anon },
241 generics: self.generics,
242 item: ScopeItem::Struct {
243 token: self.token,
244 fields,
245 },
246 semi,
247 impls: self.impls,
248 generated: vec![],
249 };
250
251 AnonScope(scope, field_val_toks)
252 }
253}
254
255#[derive(Debug)]
262pub struct AnonScope(Scope, TokenStream);
263
264impl std::ops::Deref for AnonScope {
265 type Target = Scope;
266 fn deref(&self) -> &Scope {
267 &self.0
268 }
269}
270impl std::ops::DerefMut for AnonScope {
271 fn deref_mut(&mut self) -> &mut Scope {
272 &mut self.0
273 }
274}
275
276impl AnonScope {
277 pub fn expand(mut self) -> TokenStream {
283 self.expand_impl_self();
284 self.into_token_stream()
285 }
286}
287
288impl ToTokens for AnonScope {
289 fn to_tokens(&self, tokens: &mut TokenStream) {
290 let scope = &self.0;
291 let field_val_toks = &self.1;
292
293 tokens.append_all(quote! {
294 {
295 #scope
296
297 _Anon {
298 #field_val_toks
299 }
300 }
301 });
302 }
303}
304
305mod parsing {
306 use super::*;
307 use proc_macro_error3::abort;
308 use syn::parse::{Error, Parse, ParseStream, Result};
309 use syn::{braced, parenthesized};
310
311 fn parse_impl(in_ident: Option<&Ident>, input: ParseStream) -> Result<ItemImpl> {
312 let mut attrs = input.call(Attribute::parse_outer)?;
313 let defaultness: Option<Token![default]> = input.parse()?;
314 let unsafety: Option<Token![unsafe]> = input.parse()?;
315 let impl_token: Token![impl] = input.parse()?;
316
317 let has_generics = input.peek(Token![<])
318 && (input.peek2(Token![>])
319 || input.peek2(Token![#])
320 || (input.peek2(Ident) || input.peek2(syn::Lifetime))
321 && (input.peek3(Token![:])
322 || input.peek3(Token![,])
323 || input.peek3(Token![>])
324 || input.peek3(Token![=]))
325 || input.peek2(Token![const]));
326 let mut generics: Generics = if has_generics {
327 input.parse()?
328 } else {
329 Generics::default()
330 };
331
332 let mut first_ty: Type = input.parse()?;
333 let self_ty: Type;
334 let trait_;
335
336 let is_impl_for = input.peek(Token![for]);
337 if is_impl_for {
338 let for_token: Token![for] = input.parse()?;
339 let mut first_ty_ref = &first_ty;
340 while let Type::Group(ty) = first_ty_ref {
341 first_ty_ref = &ty.elem;
342 }
343 if let Type::Path(_) = first_ty_ref {
344 while let Type::Group(ty) = first_ty {
345 first_ty = *ty.elem;
346 }
347 if let Type::Path(TypePath {
348 attrs,
349 qself: None,
350 path,
351 }) = first_ty
352 {
353 error_on_attrs(&attrs);
354 trait_ = Some((path, for_token));
355 } else {
356 unreachable!();
357 }
358 } else {
359 return Err(Error::new(for_token.span(), "for without target trait"));
360 }
361 self_ty = input.parse()?;
362 } else {
363 trait_ = None;
364 self_ty = first_ty;
365 }
366
367 generics.where_clause = input.parse()?;
368
369 if self_ty != parse_quote! { Self } {
370 if let Some(ident) = in_ident {
371 if !matches!(self_ty, Type::Path(TypePath {
372 attrs: _,
373 qself: None,
374 path: syn::Path {
375 leading_colon: None,
376 ref segments,
377 }
378 }) if segments.len() == 1 && segments.first().unwrap().ident == *ident)
379 {
380 abort!(
381 self_ty.span(),
382 format!(
383 "expected `Self` or `{0}` or `{0}<...>` or `Trait for Self`, etc",
384 ident
385 )
386 );
387 }
388 } else {
389 abort!(self_ty.span(), "expected `Self` or `Trait for Self`");
390 }
391 }
392
393 let content;
394 let brace_token = braced!(content in input);
395 attrs.extend(Attribute::parse_inner(&content)?);
396
397 let mut items = Vec::new();
398 while !content.is_empty() {
399 items.push(content.parse()?);
400 }
401
402 let mut modifiers = syn::ImplModifiers::default();
403 modifiers.defaultness = defaultness;
404
405 Ok(ItemImpl {
406 attrs,
407 modifiers,
408 unsafety,
409 impl_token,
410 generics,
411 trait_,
412 self_ty: Box::new(self_ty),
413 brace_token,
414 items,
415 })
416 }
417
418 impl AnonField {
419 fn check_is_fixed(ty: &Type, input_span: Span) -> Result<()> {
420 let is_fixed = match ty {
421 Type::ImplTrait(_) | Type::Infer(_) => false,
422 ty => {
423 struct IsFixed(bool);
424 let mut checker = IsFixed(true);
425
426 impl<'ast> syn::visit::Visit<'ast> for IsFixed {
427 fn visit_type(&mut self, node: &'ast Type) {
428 if matches!(node, Type::ImplTrait(_) | Type::Infer(_)) {
429 self.0 = false;
430 }
431 }
432 }
433 syn::visit::visit_type(&mut checker, ty);
434
435 checker.0
436 }
437 };
438
439 if is_fixed {
440 Ok(())
441 } else {
442 Err(Error::new(
443 input_span,
444 "require either a fixed type or a value assignment",
445 ))
446 }
447 }
448
449 fn parse_named(input: ParseStream) -> Result<Self> {
450 let attrs = input.call(Attribute::parse_outer)?;
451 let vis = input.parse()?;
452
453 let ident = if input.peek(Token![_]) {
454 let _: Token![_] = input.parse()?;
455 None
456 } else {
457 Some(input.parse::<Ident>()?)
458 };
459
460 let mut colon_token = None;
461
462 let ty = if input.peek(Colon) && !input.peek2(Colon) {
464 colon_token = Some(input.parse()?);
465 input.parse()?
466 } else {
467 parse_quote! { _ }
468 };
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,
481 colon_token,
482 ty,
483 assignment,
484 })
485 }
486
487 fn parse_unnamed(input: ParseStream) -> Result<Self> {
488 let attrs = input.call(Attribute::parse_outer)?;
489 let vis = input.parse()?;
490
491 let ty = input.parse()?;
492
493 let mut assignment = None;
494 if let Ok(eq) = input.parse::<Eq>() {
495 assignment = Some((eq, input.parse()?));
496 } else {
497 Self::check_is_fixed(&ty, input.span())?;
498 }
499
500 Ok(AnonField {
501 attrs,
502 vis,
503 ident: None,
504 colon_token: None,
505 ty,
506 assignment,
507 })
508 }
509 }
510
511 impl Parse for Anon {
512 fn parse(input: ParseStream) -> Result<Self> {
513 let attrs = input.call(Attribute::parse_outer)?;
514 let token = input.parse::<Token![struct]>()?;
515
516 let mut generics = input.parse::<Generics>()?;
517
518 let mut lookahead = input.lookahead1();
519 if lookahead.peek(Token![where]) {
520 generics.where_clause = Some(input.parse()?);
521 lookahead = input.lookahead1();
522 }
523
524 let style;
525 let fields;
526 if generics.where_clause.is_none() && lookahead.peek(Paren) {
527 let content;
528 let paren_token = parenthesized!(content in input);
529 fields = content.parse_terminated(AnonField::parse_unnamed, Token![,])?;
530
531 lookahead = input.lookahead1();
532 if lookahead.peek(Token![where]) {
533 generics.where_clause = Some(input.parse()?);
534 lookahead = input.lookahead1();
535 }
536
537 if lookahead.peek(Semi) {
538 style = StructStyle::Tuple(paren_token, input.parse()?);
539 } else {
540 return Err(lookahead.error());
541 }
542 } else if lookahead.peek(Brace) {
543 let content;
544 let brace_token = braced!(content in input);
545 style = StructStyle::Regular(brace_token);
546 fields = content.parse_terminated(AnonField::parse_named, Token![,])?;
547 } else if lookahead.peek(Semi) {
548 style = StructStyle::Unit(input.parse()?);
549 fields = Punctuated::new();
550 } else {
551 return Err(lookahead.error());
552 }
553
554 let mut impls = Vec::new();
555 while !input.is_empty() {
556 impls.push(parse_impl(None, input)?);
557 }
558
559 Ok(Anon {
560 attrs,
561 token,
562 generics,
563 style,
564 fields,
565 impls,
566 })
567 }
568 }
569}