Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/syn/generics.rs
38271 views
1
// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3
use crate::attr::Attribute;
4
use crate::expr::Expr;
5
use crate::ident::Ident;
6
use crate::lifetime::Lifetime;
7
use crate::path::Path;
8
use crate::punctuated::{Iter, IterMut, Punctuated};
9
use crate::token;
10
use crate::ty::Type;
11
use proc_macro2::TokenStream;
12
#[cfg(all(feature = "printing", feature = "extra-traits"))]
13
use std::fmt::{self, Debug};
14
#[cfg(all(feature = "printing", feature = "extra-traits"))]
15
use std::hash::{Hash, Hasher};
16
17
ast_struct! {
18
/// Lifetimes and type parameters attached to a declaration of a function,
19
/// enum, trait, etc.
20
///
21
/// This struct represents two distinct optional syntactic elements,
22
/// [generic parameters] and [where clause]. In some locations of the
23
/// grammar, there may be other tokens in between these two things.
24
///
25
/// [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters
26
/// [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses
27
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
28
pub struct Generics {
29
pub lt_token: Option<Token![<]>,
30
pub params: Punctuated<GenericParam, Token![,]>,
31
pub gt_token: Option<Token![>]>,
32
pub where_clause: Option<WhereClause>,
33
}
34
}
35
36
ast_enum_of_structs! {
37
/// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
38
/// `'a: 'b`, `const LEN: usize`.
39
///
40
/// # Syntax tree enum
41
///
42
/// This type is a [syntax tree enum].
43
///
44
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
45
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
46
pub enum GenericParam {
47
/// A lifetime parameter: `'a: 'b + 'c + 'd`.
48
Lifetime(LifetimeParam),
49
50
/// A generic type parameter: `T: Into<String>`.
51
Type(TypeParam),
52
53
/// A const generic parameter: `const LENGTH: usize`.
54
Const(ConstParam),
55
}
56
}
57
58
ast_struct! {
59
/// A lifetime definition: `'a: 'b + 'c + 'd`.
60
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
61
pub struct LifetimeParam {
62
pub attrs: Vec<Attribute>,
63
pub lifetime: Lifetime,
64
pub colon_token: Option<Token![:]>,
65
pub bounds: Punctuated<Lifetime, Token![+]>,
66
}
67
}
68
69
ast_struct! {
70
/// A generic type parameter: `T: Into<String>`.
71
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
72
pub struct TypeParam {
73
pub attrs: Vec<Attribute>,
74
pub ident: Ident,
75
pub colon_token: Option<Token![:]>,
76
pub bounds: Punctuated<TypeParamBound, Token![+]>,
77
pub eq_token: Option<Token![=]>,
78
pub default: Option<Type>,
79
}
80
}
81
82
ast_struct! {
83
/// A const generic parameter: `const LENGTH: usize`.
84
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
85
pub struct ConstParam {
86
pub attrs: Vec<Attribute>,
87
pub const_token: Token![const],
88
pub ident: Ident,
89
pub colon_token: Token![:],
90
pub ty: Type,
91
pub eq_token: Option<Token![=]>,
92
pub default: Option<Expr>,
93
}
94
}
95
96
impl Default for Generics {
97
fn default() -> Self {
98
Generics {
99
lt_token: None,
100
params: Punctuated::new(),
101
gt_token: None,
102
where_clause: None,
103
}
104
}
105
}
106
107
impl Generics {
108
return_impl_trait! {
109
/// Iterator over the lifetime parameters in `self.params`.
110
pub fn lifetimes(&self) -> impl Iterator<Item = &LifetimeParam> [Lifetimes] {
111
Lifetimes(self.params.iter())
112
}
113
}
114
115
return_impl_trait! {
116
/// Iterator over the lifetime parameters in `self.params`.
117
pub fn lifetimes_mut(&mut self) -> impl Iterator<Item = &mut LifetimeParam> [LifetimesMut] {
118
LifetimesMut(self.params.iter_mut())
119
}
120
}
121
122
return_impl_trait! {
123
/// Iterator over the type parameters in `self.params`.
124
pub fn type_params(&self) -> impl Iterator<Item = &TypeParam> [TypeParams] {
125
TypeParams(self.params.iter())
126
}
127
}
128
129
return_impl_trait! {
130
/// Iterator over the type parameters in `self.params`.
131
pub fn type_params_mut(&mut self) -> impl Iterator<Item = &mut TypeParam> [TypeParamsMut] {
132
TypeParamsMut(self.params.iter_mut())
133
}
134
}
135
136
return_impl_trait! {
137
/// Iterator over the constant parameters in `self.params`.
138
pub fn const_params(&self) -> impl Iterator<Item = &ConstParam> [ConstParams] {
139
ConstParams(self.params.iter())
140
}
141
}
142
143
return_impl_trait! {
144
/// Iterator over the constant parameters in `self.params`.
145
pub fn const_params_mut(&mut self) -> impl Iterator<Item = &mut ConstParam> [ConstParamsMut] {
146
ConstParamsMut(self.params.iter_mut())
147
}
148
}
149
150
/// Initializes an empty `where`-clause if there is not one present already.
151
pub fn make_where_clause(&mut self) -> &mut WhereClause {
152
self.where_clause.get_or_insert_with(|| WhereClause {
153
where_token: <Token![where]>::default(),
154
predicates: Punctuated::new(),
155
})
156
}
157
158
/// Split a type's generics into the pieces required for impl'ing a trait
159
/// for that type.
160
///
161
/// ```
162
/// # use proc_macro2::{Span, Ident};
163
/// # use quote::quote;
164
/// #
165
/// # let generics: syn::Generics = Default::default();
166
/// # let name = Ident::new("MyType", Span::call_site());
167
/// #
168
/// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
169
/// quote! {
170
/// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
171
/// // ...
172
/// }
173
/// }
174
/// # ;
175
/// ```
176
#[cfg(feature = "printing")]
177
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
178
pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
179
(
180
ImplGenerics(self),
181
TypeGenerics(self),
182
self.where_clause.as_ref(),
183
)
184
}
185
}
186
187
pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
188
189
impl<'a> Iterator for Lifetimes<'a> {
190
type Item = &'a LifetimeParam;
191
192
fn next(&mut self) -> Option<Self::Item> {
193
if let GenericParam::Lifetime(lifetime) = self.0.next()? {
194
Some(lifetime)
195
} else {
196
self.next()
197
}
198
}
199
}
200
201
pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
202
203
impl<'a> Iterator for LifetimesMut<'a> {
204
type Item = &'a mut LifetimeParam;
205
206
fn next(&mut self) -> Option<Self::Item> {
207
if let GenericParam::Lifetime(lifetime) = self.0.next()? {
208
Some(lifetime)
209
} else {
210
self.next()
211
}
212
}
213
}
214
215
pub struct TypeParams<'a>(Iter<'a, GenericParam>);
216
217
impl<'a> Iterator for TypeParams<'a> {
218
type Item = &'a TypeParam;
219
220
fn next(&mut self) -> Option<Self::Item> {
221
if let GenericParam::Type(type_param) = self.0.next()? {
222
Some(type_param)
223
} else {
224
self.next()
225
}
226
}
227
}
228
229
pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
230
231
impl<'a> Iterator for TypeParamsMut<'a> {
232
type Item = &'a mut TypeParam;
233
234
fn next(&mut self) -> Option<Self::Item> {
235
if let GenericParam::Type(type_param) = self.0.next()? {
236
Some(type_param)
237
} else {
238
self.next()
239
}
240
}
241
}
242
243
pub struct ConstParams<'a>(Iter<'a, GenericParam>);
244
245
impl<'a> Iterator for ConstParams<'a> {
246
type Item = &'a ConstParam;
247
248
fn next(&mut self) -> Option<Self::Item> {
249
if let GenericParam::Const(const_param) = self.0.next()? {
250
Some(const_param)
251
} else {
252
self.next()
253
}
254
}
255
}
256
257
pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
258
259
impl<'a> Iterator for ConstParamsMut<'a> {
260
type Item = &'a mut ConstParam;
261
262
fn next(&mut self) -> Option<Self::Item> {
263
if let GenericParam::Const(const_param) = self.0.next()? {
264
Some(const_param)
265
} else {
266
self.next()
267
}
268
}
269
}
270
271
/// Returned by `Generics::split_for_impl`.
272
#[cfg(feature = "printing")]
273
#[cfg_attr(
274
docsrs,
275
doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
276
)]
277
pub struct ImplGenerics<'a>(&'a Generics);
278
279
/// Returned by `Generics::split_for_impl`.
280
#[cfg(feature = "printing")]
281
#[cfg_attr(
282
docsrs,
283
doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
284
)]
285
pub struct TypeGenerics<'a>(&'a Generics);
286
287
/// Returned by `TypeGenerics::as_turbofish`.
288
#[cfg(feature = "printing")]
289
#[cfg_attr(
290
docsrs,
291
doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
292
)]
293
pub struct Turbofish<'a>(&'a Generics);
294
295
#[cfg(feature = "printing")]
296
macro_rules! generics_wrapper_impls {
297
($ty:ident) => {
298
#[cfg(feature = "clone-impls")]
299
#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
300
impl<'a> Clone for $ty<'a> {
301
fn clone(&self) -> Self {
302
$ty(self.0)
303
}
304
}
305
306
#[cfg(feature = "extra-traits")]
307
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
308
impl<'a> Debug for $ty<'a> {
309
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
310
formatter
311
.debug_tuple(stringify!($ty))
312
.field(self.0)
313
.finish()
314
}
315
}
316
317
#[cfg(feature = "extra-traits")]
318
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
319
impl<'a> Eq for $ty<'a> {}
320
321
#[cfg(feature = "extra-traits")]
322
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
323
impl<'a> PartialEq for $ty<'a> {
324
fn eq(&self, other: &Self) -> bool {
325
self.0 == other.0
326
}
327
}
328
329
#[cfg(feature = "extra-traits")]
330
#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
331
impl<'a> Hash for $ty<'a> {
332
fn hash<H: Hasher>(&self, state: &mut H) {
333
self.0.hash(state);
334
}
335
}
336
};
337
}
338
339
#[cfg(feature = "printing")]
340
generics_wrapper_impls!(ImplGenerics);
341
#[cfg(feature = "printing")]
342
generics_wrapper_impls!(TypeGenerics);
343
#[cfg(feature = "printing")]
344
generics_wrapper_impls!(Turbofish);
345
346
#[cfg(feature = "printing")]
347
impl<'a> TypeGenerics<'a> {
348
/// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
349
pub fn as_turbofish(&self) -> Turbofish<'a> {
350
Turbofish(self.0)
351
}
352
}
353
354
ast_struct! {
355
/// A set of bound lifetimes: `for<'a, 'b, 'c>`.
356
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
357
pub struct BoundLifetimes {
358
pub for_token: Token![for],
359
pub lt_token: Token![<],
360
pub lifetimes: Punctuated<GenericParam, Token![,]>,
361
pub gt_token: Token![>],
362
}
363
}
364
365
impl Default for BoundLifetimes {
366
fn default() -> Self {
367
BoundLifetimes {
368
for_token: Default::default(),
369
lt_token: Default::default(),
370
lifetimes: Punctuated::new(),
371
gt_token: Default::default(),
372
}
373
}
374
}
375
376
impl LifetimeParam {
377
pub fn new(lifetime: Lifetime) -> Self {
378
LifetimeParam {
379
attrs: Vec::new(),
380
lifetime,
381
colon_token: None,
382
bounds: Punctuated::new(),
383
}
384
}
385
}
386
387
impl From<Ident> for TypeParam {
388
fn from(ident: Ident) -> Self {
389
TypeParam {
390
attrs: vec![],
391
ident,
392
colon_token: None,
393
bounds: Punctuated::new(),
394
eq_token: None,
395
default: None,
396
}
397
}
398
}
399
400
ast_enum_of_structs! {
401
/// A trait or lifetime used as a bound on a type parameter.
402
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
403
#[non_exhaustive]
404
pub enum TypeParamBound {
405
Trait(TraitBound),
406
Lifetime(Lifetime),
407
PreciseCapture(PreciseCapture),
408
Verbatim(TokenStream),
409
}
410
}
411
412
ast_struct! {
413
/// A trait used as a bound on a type parameter.
414
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
415
pub struct TraitBound {
416
pub paren_token: Option<token::Paren>,
417
pub modifier: TraitBoundModifier,
418
/// The `for<'a>` in `for<'a> Foo<&'a T>`
419
pub lifetimes: Option<BoundLifetimes>,
420
/// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
421
pub path: Path,
422
}
423
}
424
425
ast_enum! {
426
/// A modifier on a trait bound, currently only used for the `?` in
427
/// `?Sized`.
428
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
429
pub enum TraitBoundModifier {
430
None,
431
Maybe(Token![?]),
432
}
433
}
434
435
ast_struct! {
436
/// Precise capturing bound: the 'use&lt;&hellip;&gt;' in `impl Trait +
437
/// use<'a, T>`.
438
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
439
pub struct PreciseCapture #full {
440
pub use_token: Token![use],
441
pub lt_token: Token![<],
442
pub params: Punctuated<CapturedParam, Token![,]>,
443
pub gt_token: Token![>],
444
}
445
}
446
447
#[cfg(feature = "full")]
448
ast_enum! {
449
/// Single parameter in a precise capturing bound.
450
#[cfg_attr(docsrs, doc(cfg(feature = "full")))]
451
#[non_exhaustive]
452
pub enum CapturedParam {
453
/// A lifetime parameter in precise capturing bound: `fn f<'a>() -> impl
454
/// Trait + use<'a>`.
455
Lifetime(Lifetime),
456
/// A type parameter or const generic parameter in precise capturing
457
/// bound: `fn f<T>() -> impl Trait + use<T>` or `fn f<const K: T>() ->
458
/// impl Trait + use<K>`.
459
Ident(Ident),
460
}
461
}
462
463
ast_struct! {
464
/// A `where` clause in a definition: `where T: Deserialize<'de>, D:
465
/// 'static`.
466
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
467
pub struct WhereClause {
468
pub where_token: Token![where],
469
pub predicates: Punctuated<WherePredicate, Token![,]>,
470
}
471
}
472
473
ast_enum_of_structs! {
474
/// A single predicate in a `where` clause: `T: Deserialize<'de>`.
475
///
476
/// # Syntax tree enum
477
///
478
/// This type is a [syntax tree enum].
479
///
480
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
481
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
482
#[non_exhaustive]
483
pub enum WherePredicate {
484
/// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
485
Lifetime(PredicateLifetime),
486
487
/// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
488
Type(PredicateType),
489
}
490
}
491
492
ast_struct! {
493
/// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
494
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
495
pub struct PredicateLifetime {
496
pub lifetime: Lifetime,
497
pub colon_token: Token![:],
498
pub bounds: Punctuated<Lifetime, Token![+]>,
499
}
500
}
501
502
ast_struct! {
503
/// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
504
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
505
pub struct PredicateType {
506
/// Any lifetimes from a `for` binding
507
pub lifetimes: Option<BoundLifetimes>,
508
/// The type being bounded
509
pub bounded_ty: Type,
510
pub colon_token: Token![:],
511
/// Trait and lifetime bounds (`Clone+Send+'static`)
512
pub bounds: Punctuated<TypeParamBound, Token![+]>,
513
}
514
}
515
516
#[cfg(feature = "parsing")]
517
pub(crate) mod parsing {
518
use crate::attr::Attribute;
519
#[cfg(feature = "full")]
520
use crate::error;
521
use crate::error::{Error, Result};
522
use crate::ext::IdentExt as _;
523
use crate::generics::{
524
BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
525
PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
526
WherePredicate,
527
};
528
#[cfg(feature = "full")]
529
use crate::generics::{CapturedParam, PreciseCapture};
530
use crate::ident::Ident;
531
use crate::lifetime::Lifetime;
532
use crate::parse::{Parse, ParseStream};
533
use crate::path::{self, ParenthesizedGenericArguments, Path, PathArguments};
534
use crate::punctuated::Punctuated;
535
use crate::token;
536
use crate::ty::Type;
537
use crate::verbatim;
538
539
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
540
impl Parse for Generics {
541
fn parse(input: ParseStream) -> Result<Self> {
542
if !input.peek(Token![<]) {
543
return Ok(Generics::default());
544
}
545
546
let lt_token: Token![<] = input.parse()?;
547
548
let mut params = Punctuated::new();
549
loop {
550
if input.peek(Token![>]) {
551
break;
552
}
553
554
let attrs = input.call(Attribute::parse_outer)?;
555
let lookahead = input.lookahead1();
556
if lookahead.peek(Lifetime) {
557
params.push_value(GenericParam::Lifetime(LifetimeParam {
558
attrs,
559
..input.parse()?
560
}));
561
} else if lookahead.peek(Ident) {
562
params.push_value(GenericParam::Type(TypeParam {
563
attrs,
564
..input.parse()?
565
}));
566
} else if lookahead.peek(Token![const]) {
567
params.push_value(GenericParam::Const(ConstParam {
568
attrs,
569
..input.parse()?
570
}));
571
} else if input.peek(Token![_]) {
572
params.push_value(GenericParam::Type(TypeParam {
573
attrs,
574
ident: input.call(Ident::parse_any)?,
575
colon_token: None,
576
bounds: Punctuated::new(),
577
eq_token: None,
578
default: None,
579
}));
580
} else {
581
return Err(lookahead.error());
582
}
583
584
if input.peek(Token![>]) {
585
break;
586
}
587
let punct = input.parse()?;
588
params.push_punct(punct);
589
}
590
591
let gt_token: Token![>] = input.parse()?;
592
593
Ok(Generics {
594
lt_token: Some(lt_token),
595
params,
596
gt_token: Some(gt_token),
597
where_clause: None,
598
})
599
}
600
}
601
602
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
603
impl Parse for GenericParam {
604
fn parse(input: ParseStream) -> Result<Self> {
605
let attrs = input.call(Attribute::parse_outer)?;
606
607
let lookahead = input.lookahead1();
608
if lookahead.peek(Ident) {
609
Ok(GenericParam::Type(TypeParam {
610
attrs,
611
..input.parse()?
612
}))
613
} else if lookahead.peek(Lifetime) {
614
Ok(GenericParam::Lifetime(LifetimeParam {
615
attrs,
616
..input.parse()?
617
}))
618
} else if lookahead.peek(Token![const]) {
619
Ok(GenericParam::Const(ConstParam {
620
attrs,
621
..input.parse()?
622
}))
623
} else {
624
Err(lookahead.error())
625
}
626
}
627
}
628
629
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
630
impl Parse for LifetimeParam {
631
fn parse(input: ParseStream) -> Result<Self> {
632
let has_colon;
633
Ok(LifetimeParam {
634
attrs: input.call(Attribute::parse_outer)?,
635
lifetime: input.parse()?,
636
colon_token: {
637
if input.peek(Token![:]) {
638
has_colon = true;
639
Some(input.parse()?)
640
} else {
641
has_colon = false;
642
None
643
}
644
},
645
bounds: {
646
let mut bounds = Punctuated::new();
647
if has_colon {
648
loop {
649
if input.peek(Token![,]) || input.peek(Token![>]) {
650
break;
651
}
652
let value = input.parse()?;
653
bounds.push_value(value);
654
if !input.peek(Token![+]) {
655
break;
656
}
657
let punct = input.parse()?;
658
bounds.push_punct(punct);
659
}
660
}
661
bounds
662
},
663
})
664
}
665
}
666
667
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
668
impl Parse for BoundLifetimes {
669
fn parse(input: ParseStream) -> Result<Self> {
670
Ok(BoundLifetimes {
671
for_token: input.parse()?,
672
lt_token: input.parse()?,
673
lifetimes: {
674
let mut lifetimes = Punctuated::new();
675
while !input.peek(Token![>]) {
676
lifetimes.push_value(input.parse()?);
677
if input.peek(Token![>]) {
678
break;
679
}
680
lifetimes.push_punct(input.parse()?);
681
}
682
lifetimes
683
},
684
gt_token: input.parse()?,
685
})
686
}
687
}
688
689
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
690
impl Parse for Option<BoundLifetimes> {
691
fn parse(input: ParseStream) -> Result<Self> {
692
if input.peek(Token![for]) {
693
input.parse().map(Some)
694
} else {
695
Ok(None)
696
}
697
}
698
}
699
700
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
701
impl Parse for TypeParam {
702
fn parse(input: ParseStream) -> Result<Self> {
703
let attrs = input.call(Attribute::parse_outer)?;
704
let ident: Ident = input.parse()?;
705
let colon_token: Option<Token![:]> = input.parse()?;
706
707
let mut bounds = Punctuated::new();
708
if colon_token.is_some() {
709
loop {
710
if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) {
711
break;
712
}
713
bounds.push_value({
714
let allow_precise_capture = false;
715
let allow_const = true;
716
TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
717
});
718
if !input.peek(Token![+]) {
719
break;
720
}
721
let punct: Token![+] = input.parse()?;
722
bounds.push_punct(punct);
723
}
724
}
725
726
let eq_token: Option<Token![=]> = input.parse()?;
727
let default = if eq_token.is_some() {
728
Some(input.parse::<Type>()?)
729
} else {
730
None
731
};
732
733
Ok(TypeParam {
734
attrs,
735
ident,
736
colon_token,
737
bounds,
738
eq_token,
739
default,
740
})
741
}
742
}
743
744
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
745
impl Parse for TypeParamBound {
746
fn parse(input: ParseStream) -> Result<Self> {
747
let allow_precise_capture = true;
748
let allow_const = true;
749
Self::parse_single(input, allow_precise_capture, allow_const)
750
}
751
}
752
753
impl TypeParamBound {
754
pub(crate) fn parse_single(
755
input: ParseStream,
756
#[cfg_attr(not(feature = "full"), allow(unused_variables))] allow_precise_capture: bool,
757
allow_const: bool,
758
) -> Result<Self> {
759
if input.peek(Lifetime) {
760
return input.parse().map(TypeParamBound::Lifetime);
761
}
762
763
#[cfg(feature = "full")]
764
{
765
if input.peek(Token![use]) {
766
let precise_capture: PreciseCapture = input.parse()?;
767
return if allow_precise_capture {
768
Ok(TypeParamBound::PreciseCapture(precise_capture))
769
} else {
770
let msg = "`use<...>` precise capturing syntax is not allowed here";
771
Err(error::new2(
772
precise_capture.use_token.span,
773
precise_capture.gt_token.span,
774
msg,
775
))
776
};
777
}
778
}
779
780
let begin = input.fork();
781
782
let content;
783
let (paren_token, content) = if input.peek(token::Paren) {
784
(Some(parenthesized!(content in input)), &content)
785
} else {
786
(None, input)
787
};
788
789
if let Some(mut bound) = TraitBound::do_parse(content, allow_const)? {
790
bound.paren_token = paren_token;
791
Ok(TypeParamBound::Trait(bound))
792
} else {
793
Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input)))
794
}
795
}
796
797
pub(crate) fn parse_multiple(
798
input: ParseStream,
799
allow_plus: bool,
800
allow_precise_capture: bool,
801
allow_const: bool,
802
) -> Result<Punctuated<Self, Token![+]>> {
803
let mut bounds = Punctuated::new();
804
loop {
805
let bound = Self::parse_single(input, allow_precise_capture, allow_const)?;
806
bounds.push_value(bound);
807
if !(allow_plus && input.peek(Token![+])) {
808
break;
809
}
810
bounds.push_punct(input.parse()?);
811
if !(input.peek(Ident::peek_any)
812
|| input.peek(Token![::])
813
|| input.peek(Token![?])
814
|| input.peek(Lifetime)
815
|| input.peek(token::Paren)
816
|| (allow_const && (input.peek(token::Bracket) || input.peek(Token![const]))))
817
{
818
break;
819
}
820
}
821
Ok(bounds)
822
}
823
}
824
825
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
826
impl Parse for TraitBound {
827
fn parse(input: ParseStream) -> Result<Self> {
828
let allow_const = false;
829
Self::do_parse(input, allow_const).map(Option::unwrap)
830
}
831
}
832
833
impl TraitBound {
834
fn do_parse(input: ParseStream, allow_const: bool) -> Result<Option<Self>> {
835
let mut lifetimes: Option<BoundLifetimes> = input.parse()?;
836
837
let is_conditionally_const = cfg!(feature = "full") && input.peek(token::Bracket);
838
let is_unconditionally_const = cfg!(feature = "full") && input.peek(Token![const]);
839
if is_conditionally_const {
840
let conditionally_const;
841
let bracket_token = bracketed!(conditionally_const in input);
842
conditionally_const.parse::<Token![const]>()?;
843
if !allow_const {
844
let msg = "`[const]` is not allowed here";
845
return Err(Error::new(bracket_token.span.join(), msg));
846
}
847
} else if is_unconditionally_const {
848
let const_token: Token![const] = input.parse()?;
849
if !allow_const {
850
let msg = "`const` is not allowed here";
851
return Err(Error::new(const_token.span, msg));
852
}
853
}
854
855
let modifier: TraitBoundModifier = input.parse()?;
856
if lifetimes.is_none() && matches!(modifier, TraitBoundModifier::Maybe(_)) {
857
lifetimes = input.parse()?;
858
}
859
860
let mut path: Path = input.parse()?;
861
if path.segments.last().unwrap().arguments.is_empty()
862
&& (input.peek(token::Paren) || input.peek(Token![::]) && input.peek3(token::Paren))
863
{
864
input.parse::<Option<Token![::]>>()?;
865
let args: ParenthesizedGenericArguments = input.parse()?;
866
let parenthesized = PathArguments::Parenthesized(args);
867
path.segments.last_mut().unwrap().arguments = parenthesized;
868
}
869
870
if lifetimes.is_some() {
871
match modifier {
872
TraitBoundModifier::None => {}
873
TraitBoundModifier::Maybe(maybe) => {
874
let msg = "`for<...>` binder not allowed with `?` trait polarity modifier";
875
return Err(Error::new(maybe.span, msg));
876
}
877
}
878
}
879
880
if is_conditionally_const || is_unconditionally_const {
881
Ok(None)
882
} else {
883
Ok(Some(TraitBound {
884
paren_token: None,
885
modifier,
886
lifetimes,
887
path,
888
}))
889
}
890
}
891
}
892
893
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
894
impl Parse for TraitBoundModifier {
895
fn parse(input: ParseStream) -> Result<Self> {
896
if input.peek(Token![?]) {
897
input.parse().map(TraitBoundModifier::Maybe)
898
} else {
899
Ok(TraitBoundModifier::None)
900
}
901
}
902
}
903
904
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
905
impl Parse for ConstParam {
906
fn parse(input: ParseStream) -> Result<Self> {
907
let mut default = None;
908
Ok(ConstParam {
909
attrs: input.call(Attribute::parse_outer)?,
910
const_token: input.parse()?,
911
ident: input.parse()?,
912
colon_token: input.parse()?,
913
ty: input.parse()?,
914
eq_token: {
915
if input.peek(Token![=]) {
916
let eq_token = input.parse()?;
917
default = Some(path::parsing::const_argument(input)?);
918
Some(eq_token)
919
} else {
920
None
921
}
922
},
923
default,
924
})
925
}
926
}
927
928
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
929
impl Parse for WhereClause {
930
fn parse(input: ParseStream) -> Result<Self> {
931
let where_token: Token![where] = input.parse()?;
932
933
if choose_generics_over_qpath(input) {
934
return Err(input
935
.error("generic parameters on `where` clauses are reserved for future use"));
936
}
937
938
Ok(WhereClause {
939
where_token,
940
predicates: {
941
let mut predicates = Punctuated::new();
942
loop {
943
if input.is_empty()
944
|| input.peek(token::Brace)
945
|| input.peek(Token![,])
946
|| input.peek(Token![;])
947
|| input.peek(Token![:]) && !input.peek(Token![::])
948
|| input.peek(Token![=])
949
{
950
break;
951
}
952
let value = input.parse()?;
953
predicates.push_value(value);
954
if !input.peek(Token![,]) {
955
break;
956
}
957
let punct = input.parse()?;
958
predicates.push_punct(punct);
959
}
960
predicates
961
},
962
})
963
}
964
}
965
966
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
967
impl Parse for Option<WhereClause> {
968
fn parse(input: ParseStream) -> Result<Self> {
969
if input.peek(Token![where]) {
970
input.parse().map(Some)
971
} else {
972
Ok(None)
973
}
974
}
975
}
976
977
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
978
impl Parse for WherePredicate {
979
fn parse(input: ParseStream) -> Result<Self> {
980
if input.peek(Lifetime) && input.peek2(Token![:]) {
981
Ok(WherePredicate::Lifetime(PredicateLifetime {
982
lifetime: input.parse()?,
983
colon_token: input.parse()?,
984
bounds: {
985
let mut bounds = Punctuated::new();
986
loop {
987
if input.is_empty()
988
|| input.peek(token::Brace)
989
|| input.peek(Token![,])
990
|| input.peek(Token![;])
991
|| input.peek(Token![:])
992
|| input.peek(Token![=])
993
{
994
break;
995
}
996
let value = input.parse()?;
997
bounds.push_value(value);
998
if !input.peek(Token![+]) {
999
break;
1000
}
1001
let punct = input.parse()?;
1002
bounds.push_punct(punct);
1003
}
1004
bounds
1005
},
1006
}))
1007
} else {
1008
Ok(WherePredicate::Type(PredicateType {
1009
lifetimes: input.parse()?,
1010
bounded_ty: input.parse()?,
1011
colon_token: input.parse()?,
1012
bounds: {
1013
let mut bounds = Punctuated::new();
1014
loop {
1015
if input.is_empty()
1016
|| input.peek(token::Brace)
1017
|| input.peek(Token![,])
1018
|| input.peek(Token![;])
1019
|| input.peek(Token![:]) && !input.peek(Token![::])
1020
|| input.peek(Token![=])
1021
{
1022
break;
1023
}
1024
bounds.push_value({
1025
let allow_precise_capture = false;
1026
let allow_const = true;
1027
TypeParamBound::parse_single(
1028
input,
1029
allow_precise_capture,
1030
allow_const,
1031
)?
1032
});
1033
if !input.peek(Token![+]) {
1034
break;
1035
}
1036
let punct = input.parse()?;
1037
bounds.push_punct(punct);
1038
}
1039
bounds
1040
},
1041
}))
1042
}
1043
}
1044
}
1045
1046
#[cfg(feature = "full")]
1047
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1048
impl Parse for PreciseCapture {
1049
fn parse(input: ParseStream) -> Result<Self> {
1050
let use_token: Token![use] = input.parse()?;
1051
let lt_token: Token![<] = input.parse()?;
1052
let mut params = Punctuated::new();
1053
loop {
1054
let lookahead = input.lookahead1();
1055
params.push_value(
1056
if lookahead.peek(Lifetime) || lookahead.peek(Ident) || input.peek(Token![Self])
1057
{
1058
input.parse::<CapturedParam>()?
1059
} else if lookahead.peek(Token![>]) {
1060
break;
1061
} else {
1062
return Err(lookahead.error());
1063
},
1064
);
1065
let lookahead = input.lookahead1();
1066
params.push_punct(if lookahead.peek(Token![,]) {
1067
input.parse::<Token![,]>()?
1068
} else if lookahead.peek(Token![>]) {
1069
break;
1070
} else {
1071
return Err(lookahead.error());
1072
});
1073
}
1074
let gt_token: Token![>] = input.parse()?;
1075
Ok(PreciseCapture {
1076
use_token,
1077
lt_token,
1078
params,
1079
gt_token,
1080
})
1081
}
1082
}
1083
1084
#[cfg(feature = "full")]
1085
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1086
impl Parse for CapturedParam {
1087
fn parse(input: ParseStream) -> Result<Self> {
1088
let lookahead = input.lookahead1();
1089
if lookahead.peek(Lifetime) {
1090
input.parse().map(CapturedParam::Lifetime)
1091
} else if lookahead.peek(Ident) || input.peek(Token![Self]) {
1092
input.call(Ident::parse_any).map(CapturedParam::Ident)
1093
} else {
1094
Err(lookahead.error())
1095
}
1096
}
1097
}
1098
1099
pub(crate) fn choose_generics_over_qpath(input: ParseStream) -> bool {
1100
// Rust syntax has an ambiguity between generic parameters and qualified
1101
// paths. In `impl <T> :: Thing<T, U> {}` this may either be a generic
1102
// inherent impl `impl<T> ::Thing<T, U>` or a non-generic inherent impl
1103
// for an associated type `impl <T>::Thing<T, U>`.
1104
//
1105
// After `<` the following continuations can only begin generics, not a
1106
// qualified path:
1107
//
1108
// `<` `>` - empty generic parameters
1109
// `<` `#` - generic parameters with attribute
1110
// `<` LIFETIME `>` - single lifetime parameter
1111
// `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
1112
// `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
1113
// `<` (LIFETIME|IDENT) `=` - generic parameter with a default
1114
// `<` const - generic const parameter
1115
//
1116
// The only truly ambiguous case is:
1117
//
1118
// `<` IDENT `>` `::` IDENT ...
1119
//
1120
// which we disambiguate in favor of generics because this is almost
1121
// always the expected one in the context of real-world code.
1122
input.peek(Token![<])
1123
&& (input.peek2(Token![>])
1124
|| input.peek2(Token![#])
1125
|| (input.peek2(Lifetime) || input.peek2(Ident))
1126
&& (input.peek3(Token![>])
1127
|| input.peek3(Token![,])
1128
|| input.peek3(Token![:]) && !input.peek3(Token![::])
1129
|| input.peek3(Token![=]))
1130
|| input.peek2(Token![const]))
1131
}
1132
1133
#[cfg(feature = "full")]
1134
pub(crate) fn choose_generics_over_qpath_after_keyword(input: ParseStream) -> bool {
1135
let input = input.fork();
1136
input.call(Ident::parse_any).unwrap(); // `impl` or `for` or `where`
1137
choose_generics_over_qpath(&input)
1138
}
1139
}
1140
1141
#[cfg(feature = "printing")]
1142
pub(crate) mod printing {
1143
use crate::attr::FilterAttrs;
1144
#[cfg(feature = "full")]
1145
use crate::expr;
1146
use crate::expr::Expr;
1147
#[cfg(feature = "full")]
1148
use crate::fixup::FixupContext;
1149
use crate::generics::{
1150
BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam,
1151
PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, Turbofish, TypeGenerics,
1152
TypeParam, WhereClause,
1153
};
1154
#[cfg(feature = "full")]
1155
use crate::generics::{CapturedParam, PreciseCapture};
1156
use crate::print::TokensOrDefault;
1157
use crate::token;
1158
use proc_macro2::TokenStream;
1159
use quote::{ToTokens, TokenStreamExt};
1160
1161
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1162
impl ToTokens for Generics {
1163
fn to_tokens(&self, tokens: &mut TokenStream) {
1164
if self.params.is_empty() {
1165
return;
1166
}
1167
1168
TokensOrDefault(&self.lt_token).to_tokens(tokens);
1169
1170
// Print lifetimes before types and consts, regardless of their
1171
// order in self.params.
1172
let mut trailing_or_empty = true;
1173
for param in self.params.pairs() {
1174
if let GenericParam::Lifetime(_) = **param.value() {
1175
param.to_tokens(tokens);
1176
trailing_or_empty = param.punct().is_some();
1177
}
1178
}
1179
for param in self.params.pairs() {
1180
match param.value() {
1181
GenericParam::Type(_) | GenericParam::Const(_) => {
1182
if !trailing_or_empty {
1183
<Token![,]>::default().to_tokens(tokens);
1184
trailing_or_empty = true;
1185
}
1186
param.to_tokens(tokens);
1187
}
1188
GenericParam::Lifetime(_) => {}
1189
}
1190
}
1191
1192
TokensOrDefault(&self.gt_token).to_tokens(tokens);
1193
}
1194
}
1195
1196
impl<'a> ToTokens for ImplGenerics<'a> {
1197
fn to_tokens(&self, tokens: &mut TokenStream) {
1198
if self.0.params.is_empty() {
1199
return;
1200
}
1201
1202
TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1203
1204
// Print lifetimes before types and consts, regardless of their
1205
// order in self.params.
1206
let mut trailing_or_empty = true;
1207
for param in self.0.params.pairs() {
1208
if let GenericParam::Lifetime(_) = **param.value() {
1209
param.to_tokens(tokens);
1210
trailing_or_empty = param.punct().is_some();
1211
}
1212
}
1213
for param in self.0.params.pairs() {
1214
if let GenericParam::Lifetime(_) = **param.value() {
1215
continue;
1216
}
1217
if !trailing_or_empty {
1218
<Token![,]>::default().to_tokens(tokens);
1219
trailing_or_empty = true;
1220
}
1221
match param.value() {
1222
GenericParam::Lifetime(_) => unreachable!(),
1223
GenericParam::Type(param) => {
1224
// Leave off the type parameter defaults
1225
tokens.append_all(param.attrs.outer());
1226
param.ident.to_tokens(tokens);
1227
if !param.bounds.is_empty() {
1228
TokensOrDefault(&param.colon_token).to_tokens(tokens);
1229
param.bounds.to_tokens(tokens);
1230
}
1231
}
1232
GenericParam::Const(param) => {
1233
// Leave off the const parameter defaults
1234
tokens.append_all(param.attrs.outer());
1235
param.const_token.to_tokens(tokens);
1236
param.ident.to_tokens(tokens);
1237
param.colon_token.to_tokens(tokens);
1238
param.ty.to_tokens(tokens);
1239
}
1240
}
1241
param.punct().to_tokens(tokens);
1242
}
1243
1244
TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1245
}
1246
}
1247
1248
impl<'a> ToTokens for TypeGenerics<'a> {
1249
fn to_tokens(&self, tokens: &mut TokenStream) {
1250
if self.0.params.is_empty() {
1251
return;
1252
}
1253
1254
TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
1255
1256
// Print lifetimes before types and consts, regardless of their
1257
// order in self.params.
1258
let mut trailing_or_empty = true;
1259
for param in self.0.params.pairs() {
1260
if let GenericParam::Lifetime(def) = *param.value() {
1261
// Leave off the lifetime bounds and attributes
1262
def.lifetime.to_tokens(tokens);
1263
param.punct().to_tokens(tokens);
1264
trailing_or_empty = param.punct().is_some();
1265
}
1266
}
1267
for param in self.0.params.pairs() {
1268
if let GenericParam::Lifetime(_) = **param.value() {
1269
continue;
1270
}
1271
if !trailing_or_empty {
1272
<Token![,]>::default().to_tokens(tokens);
1273
trailing_or_empty = true;
1274
}
1275
match param.value() {
1276
GenericParam::Lifetime(_) => unreachable!(),
1277
GenericParam::Type(param) => {
1278
// Leave off the type parameter defaults
1279
param.ident.to_tokens(tokens);
1280
}
1281
GenericParam::Const(param) => {
1282
// Leave off the const parameter defaults
1283
param.ident.to_tokens(tokens);
1284
}
1285
}
1286
param.punct().to_tokens(tokens);
1287
}
1288
1289
TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
1290
}
1291
}
1292
1293
impl<'a> ToTokens for Turbofish<'a> {
1294
fn to_tokens(&self, tokens: &mut TokenStream) {
1295
if !self.0.params.is_empty() {
1296
<Token![::]>::default().to_tokens(tokens);
1297
TypeGenerics(self.0).to_tokens(tokens);
1298
}
1299
}
1300
}
1301
1302
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1303
impl ToTokens for BoundLifetimes {
1304
fn to_tokens(&self, tokens: &mut TokenStream) {
1305
self.for_token.to_tokens(tokens);
1306
self.lt_token.to_tokens(tokens);
1307
self.lifetimes.to_tokens(tokens);
1308
self.gt_token.to_tokens(tokens);
1309
}
1310
}
1311
1312
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1313
impl ToTokens for LifetimeParam {
1314
fn to_tokens(&self, tokens: &mut TokenStream) {
1315
tokens.append_all(self.attrs.outer());
1316
self.lifetime.to_tokens(tokens);
1317
if !self.bounds.is_empty() {
1318
TokensOrDefault(&self.colon_token).to_tokens(tokens);
1319
self.bounds.to_tokens(tokens);
1320
}
1321
}
1322
}
1323
1324
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1325
impl ToTokens for TypeParam {
1326
fn to_tokens(&self, tokens: &mut TokenStream) {
1327
tokens.append_all(self.attrs.outer());
1328
self.ident.to_tokens(tokens);
1329
if !self.bounds.is_empty() {
1330
TokensOrDefault(&self.colon_token).to_tokens(tokens);
1331
self.bounds.to_tokens(tokens);
1332
}
1333
if let Some(default) = &self.default {
1334
TokensOrDefault(&self.eq_token).to_tokens(tokens);
1335
default.to_tokens(tokens);
1336
}
1337
}
1338
}
1339
1340
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1341
impl ToTokens for TraitBound {
1342
fn to_tokens(&self, tokens: &mut TokenStream) {
1343
let to_tokens = |tokens: &mut TokenStream| {
1344
self.modifier.to_tokens(tokens);
1345
self.lifetimes.to_tokens(tokens);
1346
self.path.to_tokens(tokens);
1347
};
1348
match &self.paren_token {
1349
Some(paren) => paren.surround(tokens, to_tokens),
1350
None => to_tokens(tokens),
1351
}
1352
}
1353
}
1354
1355
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1356
impl ToTokens for TraitBoundModifier {
1357
fn to_tokens(&self, tokens: &mut TokenStream) {
1358
match self {
1359
TraitBoundModifier::None => {}
1360
TraitBoundModifier::Maybe(t) => t.to_tokens(tokens),
1361
}
1362
}
1363
}
1364
1365
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1366
impl ToTokens for ConstParam {
1367
fn to_tokens(&self, tokens: &mut TokenStream) {
1368
tokens.append_all(self.attrs.outer());
1369
self.const_token.to_tokens(tokens);
1370
self.ident.to_tokens(tokens);
1371
self.colon_token.to_tokens(tokens);
1372
self.ty.to_tokens(tokens);
1373
if let Some(default) = &self.default {
1374
TokensOrDefault(&self.eq_token).to_tokens(tokens);
1375
print_const_argument(default, tokens);
1376
}
1377
}
1378
}
1379
1380
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1381
impl ToTokens for WhereClause {
1382
fn to_tokens(&self, tokens: &mut TokenStream) {
1383
if !self.predicates.is_empty() {
1384
self.where_token.to_tokens(tokens);
1385
self.predicates.to_tokens(tokens);
1386
}
1387
}
1388
}
1389
1390
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1391
impl ToTokens for PredicateLifetime {
1392
fn to_tokens(&self, tokens: &mut TokenStream) {
1393
self.lifetime.to_tokens(tokens);
1394
self.colon_token.to_tokens(tokens);
1395
self.bounds.to_tokens(tokens);
1396
}
1397
}
1398
1399
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1400
impl ToTokens for PredicateType {
1401
fn to_tokens(&self, tokens: &mut TokenStream) {
1402
self.lifetimes.to_tokens(tokens);
1403
self.bounded_ty.to_tokens(tokens);
1404
self.colon_token.to_tokens(tokens);
1405
self.bounds.to_tokens(tokens);
1406
}
1407
}
1408
1409
#[cfg(feature = "full")]
1410
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1411
impl ToTokens for PreciseCapture {
1412
fn to_tokens(&self, tokens: &mut TokenStream) {
1413
self.use_token.to_tokens(tokens);
1414
self.lt_token.to_tokens(tokens);
1415
1416
// Print lifetimes before types and consts, regardless of their
1417
// order in self.params.
1418
let mut trailing_or_empty = true;
1419
for param in self.params.pairs() {
1420
if let CapturedParam::Lifetime(_) = **param.value() {
1421
param.to_tokens(tokens);
1422
trailing_or_empty = param.punct().is_some();
1423
}
1424
}
1425
for param in self.params.pairs() {
1426
if let CapturedParam::Ident(_) = **param.value() {
1427
if !trailing_or_empty {
1428
<Token![,]>::default().to_tokens(tokens);
1429
trailing_or_empty = true;
1430
}
1431
param.to_tokens(tokens);
1432
}
1433
}
1434
1435
self.gt_token.to_tokens(tokens);
1436
}
1437
}
1438
1439
#[cfg(feature = "full")]
1440
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1441
impl ToTokens for CapturedParam {
1442
fn to_tokens(&self, tokens: &mut TokenStream) {
1443
match self {
1444
CapturedParam::Lifetime(lifetime) => lifetime.to_tokens(tokens),
1445
CapturedParam::Ident(ident) => ident.to_tokens(tokens),
1446
}
1447
}
1448
}
1449
1450
pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) {
1451
match expr {
1452
Expr::Lit(expr) => expr.to_tokens(tokens),
1453
1454
Expr::Path(expr)
1455
if expr.attrs.is_empty()
1456
&& expr.qself.is_none()
1457
&& expr.path.get_ident().is_some() =>
1458
{
1459
expr.to_tokens(tokens);
1460
}
1461
1462
#[cfg(feature = "full")]
1463
Expr::Block(expr) => expr.to_tokens(tokens),
1464
1465
#[cfg(not(feature = "full"))]
1466
Expr::Verbatim(expr) => expr.to_tokens(tokens),
1467
1468
// ERROR CORRECTION: Add braces to make sure that the
1469
// generated code is valid.
1470
_ => token::Brace::default().surround(tokens, |tokens| {
1471
#[cfg(feature = "full")]
1472
expr::printing::print_expr(expr, tokens, FixupContext::new_stmt());
1473
1474
#[cfg(not(feature = "full"))]
1475
expr.to_tokens(tokens);
1476
}),
1477
}
1478
}
1479
}
1480
1481