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}