Skip to main content

auto_default/
lib.rs

1#![doc = include_str!(concat!(env!("OUT_DIR"), "/GENERATED_BADGES"))]
2//!
3//! This crate provides an attribute macro `#[auto_default]`, which adds a default field value of
4//! `Default::default()` to fields that do not have one.
5//!
6#![doc = include_str!(concat!(env!("OUT_DIR"), "/GENERATED_ADD_DEP"))]
7//!
8//! Note: `auto-default` has *zero* dependencies. Not even `syn`! The compile times are very fast.
9//!
10//! ## Showcase
11//!
12//! Rust's [default field values](https://github.com/rust-lang/rust/issues/132162) allow
13//! the shorthand `Struct { field, .. }` instead of the lengthy `Struct { field, ..Default::default() }`
14//!
15//! For `..` instead of `..Default::default()` to work,
16//! your `Struct` needs **all** fields to have a default value.
17//!
18//! This often means `= Default::default()` boilerplate on every field, because it is
19//! very common to want field defaults to be the value of their `Default` implementation
20//!
21//! ### Before
22//!
23//! ```rust
24//! # #![feature(default_field_values)]
25//! # #![feature(const_trait_impl)]
26//! # #![feature(const_default)]
27//! # #![feature(derive_const)]
28//! # use auto_default::auto_default;
29//! # #[derive_const(Default)]
30//! # struct Rect { value: f32 }
31//! # #[derive_const(Default)]
32//! # struct Size { value: f32 }
33//! # #[derive_const(Default)]
34//! # struct Point { value: f32 }
35//! #[derive(Default)]
36//! pub struct Layout {
37//!     order: u32 = Default::default(),
38//!     location: Point = Default::default(),
39//!     size: Size = Default::default(),
40//!     content_size: Size = Default::default(),
41//!     scrollbar_size: Size = Default::default(),
42//!     border: Rect = Default::default(),
43//!     padding: Rect = Default::default(),
44//!     margin: Rect = Default::default(),
45//! }
46//! ```
47//!
48//! ### With `#[auto_default]`
49//!
50//! ```rust
51//! # #![feature(default_field_values)]
52//! # #![feature(const_trait_impl)]
53//! # #![feature(const_default)]
54//! # #![feature(derive_const)]
55//! # use auto_default::auto_default;
56//! # #[derive_const(Default)]
57//! # struct Rect { value: f32 }
58//! # #[derive_const(Default)]
59//! # struct Size { value: f32 }
60//! # #[derive_const(Default)]
61//! # struct Point { value: f32 }
62//! #[auto_default]
63//! #[derive(Default)]
64//! pub struct Layout {
65//!     order: u32,
66//!     location: Point,
67//!     size: Size,
68//!     content_size: Size,
69//!     scrollbar_size: Size,
70//!     border: Rect,
71//!     padding: Rect,
72//!     margin: Rect,
73//! }
74//! ```
75//!
76//! You can apply the [`#[auto_default]`](macro@auto_default) macro to `struct`s with named fields, and `enum`s.
77//!
78//! If any field or variant has the `#[auto_default(skip)]` attribute, a default field value of `Default::default()`
79//! will **not** be added
80use std::iter::Peekable;
81
82use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
83
84/// Adds a default field value of `Default::default()` to fields that don't have one
85///
86/// # Example
87///
88/// Turns this:
89///
90/// ```rust
91/// # #![feature(default_field_values)]
92/// # #![feature(const_trait_impl)]
93/// # #![feature(const_default)]
94/// #[auto_default]
95/// struct User {
96///     age: u8,
97///     is_admin: bool = false
98/// }
99/// # use auto_default::auto_default;
100/// ```
101///
102/// Into this:
103///
104/// ```rust
105/// # #![feature(default_field_values)]
106/// # #![feature(const_trait_impl)]
107/// # #![feature(const_default)]
108/// struct User {
109///     age: u8 = Default::default(),
110///     is_admin: bool = false
111/// }
112/// ```
113///
114/// This macro applies to `struct`s with named fields, and enums.
115///
116/// # Do not add `= Default::default()` field value to select fields
117///
118/// If you do not want a specific field to have a default, you can opt-out
119/// with `#[auto_default(skip)]`:
120///
121/// ```rust
122/// # #![feature(default_field_values)]
123/// # #![feature(const_trait_impl)]
124/// # #![feature(const_default)]
125/// #[auto_default]
126/// struct User {
127///     #[auto_default(skip)]
128///     age: u8,
129///     is_admin: bool
130/// }
131/// # use auto_default::auto_default;
132/// ```
133///
134/// The above is transformed into this:
135///
136/// ```rust
137/// # #![feature(default_field_values)]
138/// # #![feature(const_trait_impl)]
139/// # #![feature(const_default)]
140/// struct User {
141///     age: u8,
142///     is_admin: bool = Default::default()
143/// }
144/// ```
145#[proc_macro_attribute]
146pub fn auto_default(args: TokenStream, input: TokenStream) -> TokenStream {
147    let mut compile_errors = TokenStream::new();
148
149    if !args.is_empty() {
150        compile_errors.extend(create_compile_error!(
151            args.into_iter().next(),
152            "no arguments expected",
153        ));
154    }
155
156    // Input supplied by the user. All tokens from here will
157    // get sent back to `output`
158    let mut source = input.into_iter().peekable();
159
160    // We collect all tokens into here and then return this
161    let mut sink = TokenStream::new();
162
163    stream_attrs(
164        &mut source,
165        &mut sink,
166        &mut compile_errors,
167        // no skip allowed on the container, would make no sense
168        // (just don't use the `#[auto_default]` at all at that point!)
169        IsSkipAllowed(false),
170    );
171    stream_vis(&mut source, &mut sink);
172
173    // pub(in crate) struct Foo
174    //               ^^^^^^
175    let item_kind = match source.next() {
176        Some(TokenTree::Ident(kw)) if kw.to_string() == "struct" => {
177            sink.extend([kw]);
178            ItemKind::Struct
179        }
180        Some(TokenTree::Ident(kw)) if kw.to_string() == "enum" => {
181            sink.extend([kw]);
182            ItemKind::Enum
183        }
184        tt => {
185            compile_errors.extend(create_compile_error!(
186                tt,
187                "expected a `struct` or an `enum`"
188            ));
189            return compile_errors;
190        }
191    };
192
193    // struct Foo
194    //        ^^^
195    let item_ident_span = stream_ident(&mut source, &mut sink)
196        .expect("`struct` or `enum` keyword is always followed by an identifier");
197
198    // Generics
199    //
200    // struct Foo<Bar, Baz: Trait> where Baz: Quux { ... }
201    //           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
202    let source_item_fields = loop {
203        match source.next() {
204            // Fields of the struct
205            Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => break group,
206            // This token is part of the generics of the struct
207            Some(tt) => sink.extend([tt]),
208            // reached end of input
209            None => {
210                // note: if enum, this is unreachable because `enum Foo` is invalid (requires `{}`),
211                // whilst `struct Foo;` is completely valid
212                compile_errors.extend(CompileError::new(
213                    item_ident_span,
214                    "expected struct with named fields",
215                ));
216                return compile_errors;
217            }
218        }
219    };
220
221    match item_kind {
222        ItemKind::Struct => {
223            sink.extend([add_default_field_values(
224                source_item_fields,
225                &mut compile_errors,
226                // none of the fields are considered to be skipped initially
227                IsSkip(false),
228            )]);
229        }
230        ItemKind::Enum => {
231            let mut source_variants = source_item_fields.stream().into_iter().peekable();
232            let mut sink_variants = TokenStream::new();
233
234            loop {
235                // if this variant is marked #[auto_default(skip)]
236                let is_skip = stream_attrs(
237                    &mut source_variants,
238                    &mut sink_variants,
239                    &mut compile_errors,
240                    // can skip the variant, which removes auto-default for all
241                    // fields
242                    IsSkipAllowed(true),
243                );
244
245                // variants technically can have visibility, at least on a syntactic level
246                //
247                // pub Variant {  }
248                // ^^^
249                stream_vis(&mut source_variants, &mut sink_variants);
250
251                // Variant {  }
252                // ^^^^^^^
253                let Some(variant_ident_span) =
254                    stream_ident(&mut source_variants, &mut sink_variants)
255                else {
256                    // that means we have an enum with no variants, e.g.:
257                    //
258                    // enum Never {}
259                    //
260                    // When we parse the variants, there won't be an identifier
261                    break;
262                };
263
264                // only variants with named fields can be marked `#[auto_default(skip)]`
265                let mut disallow_skip = || {
266                    if is_skip.0 {
267                        compile_errors.extend(CompileError::new(
268                            variant_ident_span,
269                            concat!(
270                                "`#[auto_default(skip)]` is",
271                                " only allowed on variants with named fields"
272                            ),
273                        ));
274                    }
275                };
276
277                match source_variants.peek() {
278                    // Enum variant with named fields. Add default field values.
279                    Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => {
280                        let Some(TokenTree::Group(named_variant_fields)) = source_variants.next()
281                        else {
282                            unreachable!()
283                        };
284                        sink_variants.extend([add_default_field_values(
285                            named_variant_fields,
286                            &mut compile_errors,
287                            is_skip,
288                        )]);
289
290                        stream_enum_variant_discriminant_and_comma(
291                            &mut source_variants,
292                            &mut sink_variants,
293                        );
294                    }
295                    // Enum variant with unnamed fields.
296                    Some(TokenTree::Group(group))
297                        if group.delimiter() == Delimiter::Parenthesis =>
298                    {
299                        disallow_skip();
300                        let Some(TokenTree::Group(unnamed_variant_fields)) = source_variants.next()
301                        else {
302                            unreachable!()
303                        };
304                        sink_variants.extend([unnamed_variant_fields]);
305
306                        stream_enum_variant_discriminant_and_comma(
307                            &mut source_variants,
308                            &mut sink_variants,
309                        );
310                    }
311                    // This was a unit variant. Next variant may exist,
312                    // if it does it is parsed on next iteration
313                    Some(TokenTree::Punct(punct))
314                        if punct.as_char() == ',' || punct.as_char() == '=' =>
315                    {
316                        disallow_skip();
317                        stream_enum_variant_discriminant_and_comma(
318                            &mut source_variants,
319                            &mut sink_variants,
320                        );
321                    }
322                    // Unit variant, with no comma at the end. This is the last variant
323                    None => {
324                        disallow_skip();
325                        break;
326                    }
327                    Some(_) => unreachable!(),
328                }
329            }
330
331            let mut sink_variants = Group::new(source_item_fields.delimiter(), sink_variants);
332            sink_variants.set_span(source_item_fields.span());
333            sink.extend([sink_variants]);
334        }
335    }
336
337    sink.extend(compile_errors);
338
339    sink
340}
341
342struct IsSkip(bool);
343struct IsSkipAllowed(bool);
344
345/// Streams enum variant discriminant + comma at the end from `source` into `sink`
346///
347/// enum Example {
348///     Three,
349///          ^
350///     Two(u32) = 2,
351///             ^^^^^
352///     Four { hello: u32 } = 4,
353///                        ^^^^^
354/// }
355fn stream_enum_variant_discriminant_and_comma(source: &mut Source, sink: &mut Sink) {
356    match source.next() {
357        // No discriminant, there may be another variant after this
358        Some(TokenTree::Punct(punct)) if punct.as_char() == ',' => {
359            sink.extend([punct]);
360        }
361        // No discriminant, this is the final enum variant
362        None => {}
363        // Enum variant has a discriminant
364        Some(TokenTree::Punct(punct)) if punct.as_char() == '=' => {
365            sink.extend([punct]);
366
367            // Stream discriminant expression from `source` into `sink`
368            loop {
369                match source.next() {
370                    // End of discriminant, there may be a variant after this
371                    Some(TokenTree::Punct(punct)) if punct.as_char() == ',' => {
372                        sink.extend([punct]);
373                        break;
374                    }
375                    // This token is part of the variant's expression
376                    Some(tt) => {
377                        sink.extend([tt]);
378                    }
379                    // End of discriminant, this is the last variant
380                    None => break,
381                }
382            }
383        }
384        Some(_) => unreachable!(),
385    }
386}
387
388type Source = Peekable<proc_macro::token_stream::IntoIter>;
389type Sink = TokenStream;
390
391/// Streams the identifier from `input` into `output`, returning its span, if the identifier exists
392fn stream_ident(source: &mut Source, sink: &mut Sink) -> Option<Span> {
393    let ident = source.next()?;
394    let span = ident.span();
395    sink.extend([ident]);
396    Some(span)
397}
398
399// Parses attributes
400//
401// #[attr] #[attr] pub field: Type
402// #[attr] #[attr] struct Foo
403// #[attr] #[attr] enum Foo
404//
405// Returns `true` if `#[auto_default(skip)]` was encountered
406fn stream_attrs(
407    source: &mut Source,
408    sink: &mut Sink,
409    errors: &mut TokenStream,
410    is_skip_allowed: IsSkipAllowed,
411) -> IsSkip {
412    let mut is_skip = None;
413
414    let is_skip = loop {
415        if !matches!(source.peek(), Some(TokenTree::Punct(hash)) if *hash == '#') {
416            break is_skip;
417        };
418
419        // #[some_attr]
420        // ^
421        let pound = source.next();
422
423        // #[some_attr]
424        //  ^^^^^^^^^^^
425        let Some(TokenTree::Group(attr)) = source.next() else {
426            unreachable!()
427        };
428
429        // #[some_attr = hello]
430        //   ^^^^^^^^^^^^^^^^^
431        let mut attr_tokens = attr.stream().into_iter().peekable();
432
433        // Check if this attribute is `#[auto_default(skip)]`
434        if let Some(skip_span) = is_skip_attribute(&mut attr_tokens, errors) {
435            if is_skip.is_some() {
436                // Disallow 2 attributes on a single field:
437                //
438                // #[auto_default(skip)]
439                // #[auto_default(skip)]
440                errors.extend(CompileError::new(
441                    skip_span,
442                    "duplicate `#[auto_default(skip)]`",
443                ));
444            } else {
445                is_skip = Some(skip_span);
446            }
447            continue;
448        }
449
450        // #[attr]
451        // ^
452        sink.extend(pound);
453
454        // Re-construct the `[..]` for the attribute
455        //
456        // #[attr]
457        //  ^^^^^^
458        let mut group = Group::new(attr.delimiter(), attr_tokens.collect());
459        group.set_span(attr.span());
460
461        // #[attr]
462        //  ^^^^^^
463        sink.extend([group]);
464    };
465
466    if let Some(skip_span) = is_skip
467        && !is_skip_allowed.0
468    {
469        errors.extend(CompileError::new(
470            skip_span,
471            "`#[auto_default(skip)]` is not allowed on container",
472        ));
473    }
474
475    IsSkip(is_skip.is_some())
476}
477
478/// if `source` is exactly `auto_default(skip)`, returns `Some(span)`
479/// with `span` being the `Span` of the `skip` identifier
480fn is_skip_attribute(source: &mut Source, errors: &mut TokenStream) -> Option<Span> {
481    let Some(TokenTree::Ident(ident)) = source.peek() else {
482        return None;
483    };
484
485    if ident.to_string() != "auto_default" {
486        return None;
487    };
488
489    // #[auto_default(skip)]
490    //   ^^^^^^^^^^^^
491    let ident = source.next().unwrap();
492
493    // We know it is `#[auto_default ???]`, we need to validate that `???`
494    // is exactly `(skip)` now
495
496    // #[auto_default(skip)]
497    //   ^^^^^^^^^^^^
498    let auto_default_span = ident.span();
499
500    // #[auto_default(skip)]
501    //               ^^^^^^
502    let group = match source.next() {
503        Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Parenthesis => group,
504        Some(tt) => {
505            errors.extend(CompileError::new(tt.span(), "expected `(skip)`"));
506            return None;
507        }
508        None => {
509            errors.extend(CompileError::new(
510                auto_default_span,
511                "expected `(skip)` after this",
512            ));
513            return None;
514        }
515    };
516
517    // #[auto_default(skip)]
518    //                ^^^^
519    let mut inside = group.stream().into_iter();
520
521    // #[auto_default(skip)]
522    //                ^^^^
523    let ident_skip = match inside.next() {
524        Some(TokenTree::Ident(ident)) => ident,
525        Some(tt) => {
526            errors.extend(CompileError::new(tt.span(), "expected `skip`"));
527            return None;
528        }
529        None => {
530            errors.extend(CompileError::new(
531                group.span(),
532                "expected `(skip)`, found `()`",
533            ));
534            return None;
535        }
536    };
537
538    if ident_skip.to_string() != "skip" {
539        errors.extend(CompileError::new(ident_skip.span(), "expected `skip`"));
540        return None;
541    }
542
543    // Validate that there's nothing after `skip`
544    //
545    // #[auto_default(skip    )]
546    //                    ^^^^
547    if let Some(tt) = inside.next() {
548        errors.extend(CompileError::new(tt.span(), "unexpected token"));
549        return None;
550    }
551
552    Some(ident_skip.span())
553}
554
555fn stream_vis(source: &mut Source, sink: &mut Sink) {
556    // Remove visibility if it is present
557    //
558    // pub(in crate) struct
559    // ^^^^^^^^^^^^^
560    if let Some(TokenTree::Ident(vis)) = source.peek()
561        && vis.to_string() == "pub"
562    {
563        // pub(in crate) struct
564        // ^^^
565        sink.extend(source.next());
566
567        if let Some(TokenTree::Group(group)) = source.peek()
568            && let Delimiter::Parenthesis = group.delimiter()
569        {
570            // pub(in crate) struct
571            //    ^^^^^^^^^^
572            sink.extend(source.next());
573        }
574    };
575}
576
577#[derive(PartialEq)]
578enum ItemKind {
579    Struct,
580    Enum,
581}
582
583/// `fields` is [`StructFields`] in the grammar.
584///
585/// It is the curly braces, and everything within, for a struct with named fields,
586/// or an enum variant with named fields.
587///
588/// These fields are transformed by adding `= Default::default()` to every
589/// field that doesn't already have a default value.
590///
591/// If a field is marked with `#[auto_default(skip)]`, no default value will be
592/// added
593///
594/// [`StructFields`]: https://doc.rust-lang.org/reference/items/structs.html#grammar-StructFields
595fn add_default_field_values(
596    fields: Group,
597    compile_errors: &mut TokenStream,
598    is_skip_variant: IsSkip,
599) -> Group {
600    // All the tokens corresponding to the struct's field, passed by the user
601    // These tokens will eventually all be sent to `output_fields`,
602    // plus a few extra for any `Default::default()` that we output
603    let mut input_fields = fields.stream().into_iter().peekable();
604
605    // The tokens corresponding to the fields of the output struct
606    let mut output_fields = TokenStream::new();
607
608    // Parses all fields.
609    // Each iteration parses a single field
610    'parse_field: loop {
611        let is_skip_field = stream_attrs(
612            &mut input_fields,
613            &mut output_fields,
614            compile_errors,
615            IsSkipAllowed(true),
616        );
617        let is_skip = is_skip_field.0 || is_skip_variant.0;
618        stream_vis(&mut input_fields, &mut output_fields);
619        let Some(field_ident_span) = stream_ident(&mut input_fields, &mut output_fields) else {
620            // No fields. e.g.: `struct Struct {}`
621            break;
622        };
623
624        // field: Type
625        //      ^
626        output_fields.extend(input_fields.next());
627
628        // Everything after the `:` in the field
629        //
630        // Involves:
631        //
632        // - Adding default value of `= Default::default()` if one is not present
633        // - Continue to next iteration of the loop
634        loop {
635            match input_fields.peek() {
636                // This field has a custom default field value
637                //
638                // field: Type = default
639                //             ^
640                Some(TokenTree::Punct(p)) if p.as_char() == '=' => {
641                    if is_skip {
642                        compile_errors.extend(CompileError::new(
643                            field_ident_span,
644                            concat!(
645                                "this field is marked `#[auto_default(skip)]`,",
646                                " which does nothing since this field has a",
647                                " default value: `= ...`\n",
648                                "the attribute `#[auto_default(skip)]` can be removed"
649                            ),
650                        ));
651                    }
652
653                    loop {
654                        match input_fields.next() {
655                            Some(TokenTree::Punct(p)) if p == ',' => {
656                                output_fields.extend([p]);
657                                // Comma after field. Field is finished.
658                                continue 'parse_field;
659                            }
660                            Some(tt) => output_fields.extend([tt]),
661                            // End of input. Field is finished. This is the last field
662                            None => break 'parse_field,
663                        }
664                    }
665                }
666                // Reached end of field, has comma at the end, no custom default value
667                //
668                // field: Type,
669                //            ^
670                Some(TokenTree::Punct(p)) if p.as_char() == ',' => {
671                    // Insert default value before the comma
672                    //
673                    // field: Type = Default::default(),
674                    //             ^^^^^^^^^^^^^^^^^^^^
675                    if !is_skip {
676                        output_fields.extend(default(field_ident_span));
677                    }
678                    // field: Type = Default::default(),
679                    //                                 ^
680                    output_fields.extend(input_fields.next());
681                    // Next iteration handles the next field
682                    continue 'parse_field;
683                }
684                // This token is part of the field's type
685                //
686                // field: some::Type
687                //              ^^^^
688                Some(_) => output_fields.extend(input_fields.next()),
689                // Reached end of input, and it has no comma.
690                // This is the last field.
691                //
692                // struct Foo {
693                //     field: Type
694                //                ^
695                // }
696                None => {
697                    if !is_skip {
698                        output_fields.extend(default(field_ident_span));
699                    }
700                    // No more fields
701                    break 'parse_field;
702                }
703            }
704        }
705    }
706    let mut g = Group::new(Delimiter::Brace, output_fields);
707    g.set_span(fields.span());
708    g
709}
710
711// = ::core::default::Default::default()
712fn default(span: Span) -> [TokenTree; 14] {
713    [
714        TokenTree::Punct(Punct::new('=', Spacing::Alone)),
715        TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(span),
716        TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(span),
717        TokenTree::Ident(Ident::new("core", span)),
718        TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(span),
719        TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(span),
720        TokenTree::Ident(Ident::new("default", span)),
721        TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(span),
722        TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(span),
723        TokenTree::Ident(Ident::new("Default", span)),
724        TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(span),
725        TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(span),
726        TokenTree::Ident(Ident::new("default", span)),
727        TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())).with_span(span),
728    ]
729}
730
731macro_rules! create_compile_error {
732    ($spanned:expr, $($tt:tt)*) => {{
733        let span = if let Some(spanned) = $spanned {
734            spanned.span()
735        } else {
736            Span::call_site()
737        };
738        CompileError::new(span, format!($($tt)*))
739    }};
740}
741use create_compile_error;
742
743/// `.into_iter()` generates `compile_error!($message)` at `$span`
744struct CompileError {
745    /// Where the compile error is generates
746    pub span: Span,
747    /// Message of the compile error
748    pub message: String,
749}
750
751impl CompileError {
752    /// Create a new compile error
753    pub fn new(span: Span, message: impl AsRef<str>) -> Self {
754        Self {
755            span,
756            message: message.as_ref().to_string(),
757        }
758    }
759}
760
761impl IntoIterator for CompileError {
762    type Item = TokenTree;
763    type IntoIter = std::array::IntoIter<Self::Item, 8>;
764
765    fn into_iter(self) -> Self::IntoIter {
766        [
767            TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(self.span),
768            TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(self.span),
769            TokenTree::Ident(Ident::new("core", self.span)),
770            TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(self.span),
771            TokenTree::Punct(Punct::new(':', Spacing::Joint)).with_span(self.span),
772            TokenTree::Ident(Ident::new("compile_error", self.span)),
773            TokenTree::Punct(Punct::new('!', Spacing::Alone)).with_span(self.span),
774            TokenTree::Group(Group::new(Delimiter::Brace, {
775                TokenStream::from(
776                    TokenTree::Literal(Literal::string(&self.message)).with_span(self.span),
777                )
778            }))
779            .with_span(self.span),
780        ]
781        .into_iter()
782    }
783}
784
785trait TokenTreeExt {
786    /// Set span of `TokenTree` without needing to create a new binding
787    fn with_span(self, span: Span) -> TokenTree;
788}
789
790impl TokenTreeExt for TokenTree {
791    fn with_span(mut self, span: Span) -> TokenTree {
792        self.set_span(span);
793        self
794    }
795}