Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/syn/ty.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::generics::{BoundLifetimes, TypeParamBound};
6
use crate::ident::Ident;
7
use crate::lifetime::Lifetime;
8
use crate::lit::LitStr;
9
use crate::mac::Macro;
10
use crate::path::{Path, QSelf};
11
use crate::punctuated::Punctuated;
12
use crate::token;
13
use proc_macro2::TokenStream;
14
15
ast_enum_of_structs! {
16
/// The possible types that a Rust value could have.
17
///
18
/// # Syntax tree enum
19
///
20
/// This type is a [syntax tree enum].
21
///
22
/// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
23
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
24
#[non_exhaustive]
25
pub enum Type {
26
/// A fixed size array type: `[T; n]`.
27
Array(TypeArray),
28
29
/// A bare function type: `fn(usize) -> bool`.
30
BareFn(TypeBareFn),
31
32
/// A type contained within invisible delimiters.
33
Group(TypeGroup),
34
35
/// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or
36
/// a lifetime.
37
ImplTrait(TypeImplTrait),
38
39
/// Indication that a type should be inferred by the compiler: `_`.
40
Infer(TypeInfer),
41
42
/// A macro in the type position.
43
Macro(TypeMacro),
44
45
/// The never type: `!`.
46
Never(TypeNever),
47
48
/// A parenthesized type equivalent to the inner type.
49
Paren(TypeParen),
50
51
/// A path like `std::slice::Iter`, optionally qualified with a
52
/// self-type as in `<Vec<T> as SomeTrait>::Associated`.
53
Path(TypePath),
54
55
/// A raw pointer type: `*const T` or `*mut T`.
56
Ptr(TypePtr),
57
58
/// A reference type: `&'a T` or `&'a mut T`.
59
Reference(TypeReference),
60
61
/// A dynamically sized slice type: `[T]`.
62
Slice(TypeSlice),
63
64
/// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a
65
/// trait or a lifetime.
66
TraitObject(TypeTraitObject),
67
68
/// A tuple type: `(A, B, C, String)`.
69
Tuple(TypeTuple),
70
71
/// Tokens in type position not interpreted by Syn.
72
Verbatim(TokenStream),
73
74
// For testing exhaustiveness in downstream code, use the following idiom:
75
//
76
// match ty {
77
// #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
78
//
79
// Type::Array(ty) => {...}
80
// Type::BareFn(ty) => {...}
81
// ...
82
// Type::Verbatim(ty) => {...}
83
//
84
// _ => { /* some sane fallback */ }
85
// }
86
//
87
// This way we fail your tests but don't break your library when adding
88
// a variant. You will be notified by a test failure when a variant is
89
// added, so that you can add code to handle it, but your library will
90
// continue to compile and work for downstream users in the interim.
91
}
92
}
93
94
ast_struct! {
95
/// A fixed size array type: `[T; n]`.
96
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
97
pub struct TypeArray {
98
pub bracket_token: token::Bracket,
99
pub elem: Box<Type>,
100
pub semi_token: Token![;],
101
pub len: Expr,
102
}
103
}
104
105
ast_struct! {
106
/// A bare function type: `fn(usize) -> bool`.
107
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
108
pub struct TypeBareFn {
109
pub lifetimes: Option<BoundLifetimes>,
110
pub unsafety: Option<Token![unsafe]>,
111
pub abi: Option<Abi>,
112
pub fn_token: Token![fn],
113
pub paren_token: token::Paren,
114
pub inputs: Punctuated<BareFnArg, Token![,]>,
115
pub variadic: Option<BareVariadic>,
116
pub output: ReturnType,
117
}
118
}
119
120
ast_struct! {
121
/// A type contained within invisible delimiters.
122
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
123
pub struct TypeGroup {
124
pub group_token: token::Group,
125
pub elem: Box<Type>,
126
}
127
}
128
129
ast_struct! {
130
/// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or
131
/// a lifetime.
132
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
133
pub struct TypeImplTrait {
134
pub impl_token: Token![impl],
135
pub bounds: Punctuated<TypeParamBound, Token![+]>,
136
}
137
}
138
139
ast_struct! {
140
/// Indication that a type should be inferred by the compiler: `_`.
141
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
142
pub struct TypeInfer {
143
pub underscore_token: Token![_],
144
}
145
}
146
147
ast_struct! {
148
/// A macro in the type position.
149
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
150
pub struct TypeMacro {
151
pub mac: Macro,
152
}
153
}
154
155
ast_struct! {
156
/// The never type: `!`.
157
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
158
pub struct TypeNever {
159
pub bang_token: Token![!],
160
}
161
}
162
163
ast_struct! {
164
/// A parenthesized type equivalent to the inner type.
165
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
166
pub struct TypeParen {
167
pub paren_token: token::Paren,
168
pub elem: Box<Type>,
169
}
170
}
171
172
ast_struct! {
173
/// A path like `std::slice::Iter`, optionally qualified with a
174
/// self-type as in `<Vec<T> as SomeTrait>::Associated`.
175
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
176
pub struct TypePath {
177
pub qself: Option<QSelf>,
178
pub path: Path,
179
}
180
}
181
182
ast_struct! {
183
/// A raw pointer type: `*const T` or `*mut T`.
184
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
185
pub struct TypePtr {
186
pub star_token: Token![*],
187
pub const_token: Option<Token![const]>,
188
pub mutability: Option<Token![mut]>,
189
pub elem: Box<Type>,
190
}
191
}
192
193
ast_struct! {
194
/// A reference type: `&'a T` or `&'a mut T`.
195
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
196
pub struct TypeReference {
197
pub and_token: Token![&],
198
pub lifetime: Option<Lifetime>,
199
pub mutability: Option<Token![mut]>,
200
pub elem: Box<Type>,
201
}
202
}
203
204
ast_struct! {
205
/// A dynamically sized slice type: `[T]`.
206
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
207
pub struct TypeSlice {
208
pub bracket_token: token::Bracket,
209
pub elem: Box<Type>,
210
}
211
}
212
213
ast_struct! {
214
/// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a
215
/// trait or a lifetime.
216
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
217
pub struct TypeTraitObject {
218
pub dyn_token: Option<Token![dyn]>,
219
pub bounds: Punctuated<TypeParamBound, Token![+]>,
220
}
221
}
222
223
ast_struct! {
224
/// A tuple type: `(A, B, C, String)`.
225
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
226
pub struct TypeTuple {
227
pub paren_token: token::Paren,
228
pub elems: Punctuated<Type, Token![,]>,
229
}
230
}
231
232
ast_struct! {
233
/// The binary interface of a function: `extern "C"`.
234
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
235
pub struct Abi {
236
pub extern_token: Token![extern],
237
pub name: Option<LitStr>,
238
}
239
}
240
241
ast_struct! {
242
/// An argument in a function type: the `usize` in `fn(usize) -> bool`.
243
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
244
pub struct BareFnArg {
245
pub attrs: Vec<Attribute>,
246
pub name: Option<(Ident, Token![:])>,
247
pub ty: Type,
248
}
249
}
250
251
ast_struct! {
252
/// The variadic argument of a function pointer like `fn(usize, ...)`.
253
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
254
pub struct BareVariadic {
255
pub attrs: Vec<Attribute>,
256
pub name: Option<(Ident, Token![:])>,
257
pub dots: Token![...],
258
pub comma: Option<Token![,]>,
259
}
260
}
261
262
ast_enum! {
263
/// Return type of a function signature.
264
#[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
265
pub enum ReturnType {
266
/// Return type is not specified.
267
///
268
/// Functions default to `()` and closures default to type inference.
269
Default,
270
/// A particular type is returned.
271
Type(Token![->], Box<Type>),
272
}
273
}
274
275
#[cfg(feature = "parsing")]
276
pub(crate) mod parsing {
277
use crate::attr::Attribute;
278
use crate::error::{self, Result};
279
use crate::ext::IdentExt as _;
280
use crate::generics::{BoundLifetimes, TraitBound, TraitBoundModifier, TypeParamBound};
281
use crate::ident::Ident;
282
use crate::lifetime::Lifetime;
283
use crate::mac::{self, Macro};
284
use crate::parse::{Parse, ParseStream};
285
use crate::path;
286
use crate::path::{Path, PathArguments, QSelf};
287
use crate::punctuated::Punctuated;
288
use crate::token;
289
use crate::ty::{
290
Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup,
291
TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr,
292
TypeReference, TypeSlice, TypeTraitObject, TypeTuple,
293
};
294
use crate::verbatim;
295
use proc_macro2::Span;
296
297
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
298
impl Parse for Type {
299
fn parse(input: ParseStream) -> Result<Self> {
300
let allow_plus = true;
301
let allow_group_generic = true;
302
ambig_ty(input, allow_plus, allow_group_generic)
303
}
304
}
305
306
impl Type {
307
/// In some positions, types may not contain the `+` character, to
308
/// disambiguate them. For example in the expression `1 as T`, T may not
309
/// contain a `+` character.
310
///
311
/// This parser does not allow a `+`, while the default parser does.
312
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
313
pub fn without_plus(input: ParseStream) -> Result<Self> {
314
let allow_plus = false;
315
let allow_group_generic = true;
316
ambig_ty(input, allow_plus, allow_group_generic)
317
}
318
}
319
320
pub(crate) fn ambig_ty(
321
input: ParseStream,
322
allow_plus: bool,
323
allow_group_generic: bool,
324
) -> Result<Type> {
325
let begin = input.fork();
326
327
if input.peek(token::Group) {
328
let mut group: TypeGroup = input.parse()?;
329
if input.peek(Token![::]) && input.peek3(Ident::peek_any) {
330
if let Type::Path(mut ty) = *group.elem {
331
Path::parse_rest(input, &mut ty.path, false)?;
332
return Ok(Type::Path(ty));
333
} else {
334
return Ok(Type::Path(TypePath {
335
qself: Some(QSelf {
336
lt_token: Token![<](group.group_token.span),
337
position: 0,
338
as_token: None,
339
gt_token: Token![>](group.group_token.span),
340
ty: group.elem,
341
}),
342
path: Path::parse_helper(input, false)?,
343
}));
344
}
345
} else if input.peek(Token![<]) && allow_group_generic
346
|| input.peek(Token![::]) && input.peek3(Token![<])
347
{
348
if let Type::Path(mut ty) = *group.elem {
349
let arguments = &mut ty.path.segments.last_mut().unwrap().arguments;
350
if arguments.is_none() {
351
*arguments = PathArguments::AngleBracketed(input.parse()?);
352
Path::parse_rest(input, &mut ty.path, false)?;
353
return Ok(Type::Path(ty));
354
} else {
355
group.elem = Box::new(Type::Path(ty));
356
}
357
}
358
}
359
return Ok(Type::Group(group));
360
}
361
362
let mut lifetimes = None::<BoundLifetimes>;
363
let mut lookahead = input.lookahead1();
364
if lookahead.peek(Token![for]) {
365
lifetimes = input.parse()?;
366
lookahead = input.lookahead1();
367
if !lookahead.peek(Ident)
368
&& !lookahead.peek(Token![fn])
369
&& !lookahead.peek(Token![unsafe])
370
&& !lookahead.peek(Token![extern])
371
&& !lookahead.peek(Token![super])
372
&& !lookahead.peek(Token![self])
373
&& !lookahead.peek(Token![Self])
374
&& !lookahead.peek(Token![crate])
375
|| input.peek(Token![dyn])
376
{
377
return Err(lookahead.error());
378
}
379
}
380
381
if lookahead.peek(token::Paren) {
382
let content;
383
let paren_token = parenthesized!(content in input);
384
if content.is_empty() {
385
return Ok(Type::Tuple(TypeTuple {
386
paren_token,
387
elems: Punctuated::new(),
388
}));
389
}
390
if content.peek(Lifetime) {
391
return Ok(Type::Paren(TypeParen {
392
paren_token,
393
elem: Box::new(Type::TraitObject(content.parse()?)),
394
}));
395
}
396
if content.peek(Token![?]) {
397
return Ok(Type::TraitObject(TypeTraitObject {
398
dyn_token: None,
399
bounds: {
400
let mut bounds = Punctuated::new();
401
bounds.push_value(TypeParamBound::Trait(TraitBound {
402
paren_token: Some(paren_token),
403
..content.parse()?
404
}));
405
while let Some(plus) = input.parse()? {
406
bounds.push_punct(plus);
407
bounds.push_value({
408
let allow_precise_capture = false;
409
let allow_const = false;
410
TypeParamBound::parse_single(
411
input,
412
allow_precise_capture,
413
allow_const,
414
)?
415
});
416
}
417
bounds
418
},
419
}));
420
}
421
let mut first: Type = content.parse()?;
422
if content.peek(Token![,]) {
423
return Ok(Type::Tuple(TypeTuple {
424
paren_token,
425
elems: {
426
let mut elems = Punctuated::new();
427
elems.push_value(first);
428
elems.push_punct(content.parse()?);
429
while !content.is_empty() {
430
elems.push_value(content.parse()?);
431
if content.is_empty() {
432
break;
433
}
434
elems.push_punct(content.parse()?);
435
}
436
elems
437
},
438
}));
439
}
440
if allow_plus && input.peek(Token![+]) {
441
loop {
442
let first = match first {
443
Type::Path(TypePath { qself: None, path }) => {
444
TypeParamBound::Trait(TraitBound {
445
paren_token: Some(paren_token),
446
modifier: TraitBoundModifier::None,
447
lifetimes: None,
448
path,
449
})
450
}
451
Type::TraitObject(TypeTraitObject {
452
dyn_token: None,
453
bounds,
454
}) => {
455
if bounds.len() > 1 || bounds.trailing_punct() {
456
first = Type::TraitObject(TypeTraitObject {
457
dyn_token: None,
458
bounds,
459
});
460
break;
461
}
462
match bounds.into_iter().next().unwrap() {
463
TypeParamBound::Trait(trait_bound) => {
464
TypeParamBound::Trait(TraitBound {
465
paren_token: Some(paren_token),
466
..trait_bound
467
})
468
}
469
other @ (TypeParamBound::Lifetime(_)
470
| TypeParamBound::PreciseCapture(_)
471
| TypeParamBound::Verbatim(_)) => other,
472
}
473
}
474
_ => break,
475
};
476
return Ok(Type::TraitObject(TypeTraitObject {
477
dyn_token: None,
478
bounds: {
479
let mut bounds = Punctuated::new();
480
bounds.push_value(first);
481
while let Some(plus) = input.parse()? {
482
bounds.push_punct(plus);
483
bounds.push_value({
484
let allow_precise_capture = false;
485
let allow_const = false;
486
TypeParamBound::parse_single(
487
input,
488
allow_precise_capture,
489
allow_const,
490
)?
491
});
492
}
493
bounds
494
},
495
}));
496
}
497
}
498
Ok(Type::Paren(TypeParen {
499
paren_token,
500
elem: Box::new(first),
501
}))
502
} else if lookahead.peek(Token![fn])
503
|| lookahead.peek(Token![unsafe])
504
|| lookahead.peek(Token![extern])
505
{
506
let mut bare_fn: TypeBareFn = input.parse()?;
507
bare_fn.lifetimes = lifetimes;
508
Ok(Type::BareFn(bare_fn))
509
} else if lookahead.peek(Ident)
510
|| input.peek(Token![super])
511
|| input.peek(Token![self])
512
|| input.peek(Token![Self])
513
|| input.peek(Token![crate])
514
|| lookahead.peek(Token![::])
515
|| lookahead.peek(Token![<])
516
{
517
let ty: TypePath = input.parse()?;
518
if ty.qself.is_some() {
519
return Ok(Type::Path(ty));
520
}
521
522
if input.peek(Token![!]) && !input.peek(Token![!=]) && ty.path.is_mod_style() {
523
let bang_token: Token![!] = input.parse()?;
524
let (delimiter, tokens) = mac::parse_delimiter(input)?;
525
return Ok(Type::Macro(TypeMacro {
526
mac: Macro {
527
path: ty.path,
528
bang_token,
529
delimiter,
530
tokens,
531
},
532
}));
533
}
534
535
if lifetimes.is_some() || allow_plus && input.peek(Token![+]) {
536
let mut bounds = Punctuated::new();
537
bounds.push_value(TypeParamBound::Trait(TraitBound {
538
paren_token: None,
539
modifier: TraitBoundModifier::None,
540
lifetimes,
541
path: ty.path,
542
}));
543
if allow_plus {
544
while input.peek(Token![+]) {
545
bounds.push_punct(input.parse()?);
546
if !(input.peek(Ident::peek_any)
547
|| input.peek(Token![::])
548
|| input.peek(Token![?])
549
|| input.peek(Lifetime)
550
|| input.peek(token::Paren))
551
{
552
break;
553
}
554
bounds.push_value({
555
let allow_precise_capture = false;
556
let allow_const = false;
557
TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
558
});
559
}
560
}
561
return Ok(Type::TraitObject(TypeTraitObject {
562
dyn_token: None,
563
bounds,
564
}));
565
}
566
567
Ok(Type::Path(ty))
568
} else if lookahead.peek(Token![dyn]) {
569
let dyn_token: Token![dyn] = input.parse()?;
570
let dyn_span = dyn_token.span;
571
let star_token: Option<Token![*]> = input.parse()?;
572
let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?;
573
Ok(if star_token.is_some() {
574
Type::Verbatim(verbatim::between(&begin, input))
575
} else {
576
Type::TraitObject(TypeTraitObject {
577
dyn_token: Some(dyn_token),
578
bounds,
579
})
580
})
581
} else if lookahead.peek(token::Bracket) {
582
let content;
583
let bracket_token = bracketed!(content in input);
584
let elem: Type = content.parse()?;
585
if content.peek(Token![;]) {
586
Ok(Type::Array(TypeArray {
587
bracket_token,
588
elem: Box::new(elem),
589
semi_token: content.parse()?,
590
len: content.parse()?,
591
}))
592
} else {
593
Ok(Type::Slice(TypeSlice {
594
bracket_token,
595
elem: Box::new(elem),
596
}))
597
}
598
} else if lookahead.peek(Token![*]) {
599
input.parse().map(Type::Ptr)
600
} else if lookahead.peek(Token![&]) {
601
input.parse().map(Type::Reference)
602
} else if lookahead.peek(Token![!]) && !input.peek(Token![=]) {
603
input.parse().map(Type::Never)
604
} else if lookahead.peek(Token![impl]) {
605
TypeImplTrait::parse(input, allow_plus).map(Type::ImplTrait)
606
} else if lookahead.peek(Token![_]) {
607
input.parse().map(Type::Infer)
608
} else if lookahead.peek(Lifetime) {
609
input.parse().map(Type::TraitObject)
610
} else {
611
Err(lookahead.error())
612
}
613
}
614
615
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
616
impl Parse for TypeSlice {
617
fn parse(input: ParseStream) -> Result<Self> {
618
let content;
619
Ok(TypeSlice {
620
bracket_token: bracketed!(content in input),
621
elem: content.parse()?,
622
})
623
}
624
}
625
626
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
627
impl Parse for TypeArray {
628
fn parse(input: ParseStream) -> Result<Self> {
629
let content;
630
Ok(TypeArray {
631
bracket_token: bracketed!(content in input),
632
elem: content.parse()?,
633
semi_token: content.parse()?,
634
len: content.parse()?,
635
})
636
}
637
}
638
639
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
640
impl Parse for TypePtr {
641
fn parse(input: ParseStream) -> Result<Self> {
642
let star_token: Token![*] = input.parse()?;
643
644
let lookahead = input.lookahead1();
645
let (const_token, mutability) = if lookahead.peek(Token![const]) {
646
(Some(input.parse()?), None)
647
} else if lookahead.peek(Token![mut]) {
648
(None, Some(input.parse()?))
649
} else {
650
return Err(lookahead.error());
651
};
652
653
Ok(TypePtr {
654
star_token,
655
const_token,
656
mutability,
657
elem: Box::new(input.call(Type::without_plus)?),
658
})
659
}
660
}
661
662
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
663
impl Parse for TypeReference {
664
fn parse(input: ParseStream) -> Result<Self> {
665
Ok(TypeReference {
666
and_token: input.parse()?,
667
lifetime: input.parse()?,
668
mutability: input.parse()?,
669
// & binds tighter than +, so we don't allow + here.
670
elem: Box::new(input.call(Type::without_plus)?),
671
})
672
}
673
}
674
675
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
676
impl Parse for TypeBareFn {
677
fn parse(input: ParseStream) -> Result<Self> {
678
let args;
679
let mut variadic = None;
680
681
Ok(TypeBareFn {
682
lifetimes: input.parse()?,
683
unsafety: input.parse()?,
684
abi: input.parse()?,
685
fn_token: input.parse()?,
686
paren_token: parenthesized!(args in input),
687
inputs: {
688
let mut inputs = Punctuated::new();
689
690
while !args.is_empty() {
691
let attrs = args.call(Attribute::parse_outer)?;
692
693
if inputs.empty_or_trailing()
694
&& (args.peek(Token![...])
695
|| (args.peek(Ident) || args.peek(Token![_]))
696
&& args.peek2(Token![:])
697
&& args.peek3(Token![...]))
698
{
699
variadic = Some(parse_bare_variadic(&args, attrs)?);
700
break;
701
}
702
703
let allow_self = inputs.is_empty();
704
let arg = parse_bare_fn_arg(&args, allow_self)?;
705
inputs.push_value(BareFnArg { attrs, ..arg });
706
if args.is_empty() {
707
break;
708
}
709
710
let comma = args.parse()?;
711
inputs.push_punct(comma);
712
}
713
714
inputs
715
},
716
variadic,
717
output: input.call(ReturnType::without_plus)?,
718
})
719
}
720
}
721
722
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
723
impl Parse for TypeNever {
724
fn parse(input: ParseStream) -> Result<Self> {
725
Ok(TypeNever {
726
bang_token: input.parse()?,
727
})
728
}
729
}
730
731
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
732
impl Parse for TypeInfer {
733
fn parse(input: ParseStream) -> Result<Self> {
734
Ok(TypeInfer {
735
underscore_token: input.parse()?,
736
})
737
}
738
}
739
740
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
741
impl Parse for TypeTuple {
742
fn parse(input: ParseStream) -> Result<Self> {
743
let content;
744
let paren_token = parenthesized!(content in input);
745
746
if content.is_empty() {
747
return Ok(TypeTuple {
748
paren_token,
749
elems: Punctuated::new(),
750
});
751
}
752
753
let first: Type = content.parse()?;
754
Ok(TypeTuple {
755
paren_token,
756
elems: {
757
let mut elems = Punctuated::new();
758
elems.push_value(first);
759
elems.push_punct(content.parse()?);
760
while !content.is_empty() {
761
elems.push_value(content.parse()?);
762
if content.is_empty() {
763
break;
764
}
765
elems.push_punct(content.parse()?);
766
}
767
elems
768
},
769
})
770
}
771
}
772
773
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
774
impl Parse for TypeMacro {
775
fn parse(input: ParseStream) -> Result<Self> {
776
Ok(TypeMacro {
777
mac: input.parse()?,
778
})
779
}
780
}
781
782
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
783
impl Parse for TypePath {
784
fn parse(input: ParseStream) -> Result<Self> {
785
let expr_style = false;
786
let (qself, path) = path::parsing::qpath(input, expr_style)?;
787
Ok(TypePath { qself, path })
788
}
789
}
790
791
impl ReturnType {
792
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
793
pub fn without_plus(input: ParseStream) -> Result<Self> {
794
let allow_plus = false;
795
Self::parse(input, allow_plus)
796
}
797
798
pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
799
if input.peek(Token![->]) {
800
let arrow = input.parse()?;
801
let allow_group_generic = true;
802
let ty = ambig_ty(input, allow_plus, allow_group_generic)?;
803
Ok(ReturnType::Type(arrow, Box::new(ty)))
804
} else {
805
Ok(ReturnType::Default)
806
}
807
}
808
}
809
810
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
811
impl Parse for ReturnType {
812
fn parse(input: ParseStream) -> Result<Self> {
813
let allow_plus = true;
814
Self::parse(input, allow_plus)
815
}
816
}
817
818
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
819
impl Parse for TypeTraitObject {
820
fn parse(input: ParseStream) -> Result<Self> {
821
let allow_plus = true;
822
Self::parse(input, allow_plus)
823
}
824
}
825
826
impl TypeTraitObject {
827
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
828
pub fn without_plus(input: ParseStream) -> Result<Self> {
829
let allow_plus = false;
830
Self::parse(input, allow_plus)
831
}
832
833
// Only allow multiple trait references if allow_plus is true.
834
pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
835
let dyn_token: Option<Token![dyn]> = input.parse()?;
836
let dyn_span = match &dyn_token {
837
Some(token) => token.span,
838
None => input.span(),
839
};
840
let bounds = Self::parse_bounds(dyn_span, input, allow_plus)?;
841
Ok(TypeTraitObject { dyn_token, bounds })
842
}
843
844
fn parse_bounds(
845
dyn_span: Span,
846
input: ParseStream,
847
allow_plus: bool,
848
) -> Result<Punctuated<TypeParamBound, Token![+]>> {
849
let allow_precise_capture = false;
850
let allow_const = false;
851
let bounds = TypeParamBound::parse_multiple(
852
input,
853
allow_plus,
854
allow_precise_capture,
855
allow_const,
856
)?;
857
let mut last_lifetime_span = None;
858
let mut at_least_one_trait = false;
859
for bound in &bounds {
860
match bound {
861
TypeParamBound::Trait(_) => {
862
at_least_one_trait = true;
863
break;
864
}
865
TypeParamBound::Lifetime(lifetime) => {
866
last_lifetime_span = Some(lifetime.ident.span());
867
}
868
TypeParamBound::PreciseCapture(_) | TypeParamBound::Verbatim(_) => {
869
unreachable!()
870
}
871
}
872
}
873
// Just lifetimes like `'a + 'b` is not a TraitObject.
874
if !at_least_one_trait {
875
let msg = "at least one trait is required for an object type";
876
return Err(error::new2(dyn_span, last_lifetime_span.unwrap(), msg));
877
}
878
Ok(bounds)
879
}
880
}
881
882
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
883
impl Parse for TypeImplTrait {
884
fn parse(input: ParseStream) -> Result<Self> {
885
let allow_plus = true;
886
Self::parse(input, allow_plus)
887
}
888
}
889
890
impl TypeImplTrait {
891
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
892
pub fn without_plus(input: ParseStream) -> Result<Self> {
893
let allow_plus = false;
894
Self::parse(input, allow_plus)
895
}
896
897
pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
898
let impl_token: Token![impl] = input.parse()?;
899
let allow_precise_capture = true;
900
let allow_const = true;
901
let bounds = TypeParamBound::parse_multiple(
902
input,
903
allow_plus,
904
allow_precise_capture,
905
allow_const,
906
)?;
907
let mut last_nontrait_span = None;
908
let mut at_least_one_trait = false;
909
for bound in &bounds {
910
match bound {
911
TypeParamBound::Trait(_) => {
912
at_least_one_trait = true;
913
break;
914
}
915
TypeParamBound::Lifetime(lifetime) => {
916
last_nontrait_span = Some(lifetime.ident.span());
917
}
918
TypeParamBound::PreciseCapture(precise_capture) => {
919
#[cfg(feature = "full")]
920
{
921
last_nontrait_span = Some(precise_capture.gt_token.span);
922
}
923
#[cfg(not(feature = "full"))]
924
{
925
_ = precise_capture;
926
unreachable!();
927
}
928
}
929
TypeParamBound::Verbatim(_) => {
930
// `[const] Trait`
931
at_least_one_trait = true;
932
break;
933
}
934
}
935
}
936
if !at_least_one_trait {
937
let msg = "at least one trait must be specified";
938
return Err(error::new2(
939
impl_token.span,
940
last_nontrait_span.unwrap(),
941
msg,
942
));
943
}
944
Ok(TypeImplTrait { impl_token, bounds })
945
}
946
}
947
948
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
949
impl Parse for TypeGroup {
950
fn parse(input: ParseStream) -> Result<Self> {
951
let group = crate::group::parse_group(input)?;
952
Ok(TypeGroup {
953
group_token: group.token,
954
elem: group.content.parse()?,
955
})
956
}
957
}
958
959
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
960
impl Parse for TypeParen {
961
fn parse(input: ParseStream) -> Result<Self> {
962
let allow_plus = false;
963
Self::parse(input, allow_plus)
964
}
965
}
966
967
impl TypeParen {
968
fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> {
969
let content;
970
Ok(TypeParen {
971
paren_token: parenthesized!(content in input),
972
elem: Box::new({
973
let allow_group_generic = true;
974
ambig_ty(&content, allow_plus, allow_group_generic)?
975
}),
976
})
977
}
978
}
979
980
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
981
impl Parse for BareFnArg {
982
fn parse(input: ParseStream) -> Result<Self> {
983
let allow_self = false;
984
parse_bare_fn_arg(input, allow_self)
985
}
986
}
987
988
fn parse_bare_fn_arg(input: ParseStream, allow_self: bool) -> Result<BareFnArg> {
989
let attrs = input.call(Attribute::parse_outer)?;
990
991
let begin = input.fork();
992
993
let has_mut_self = allow_self && input.peek(Token![mut]) && input.peek2(Token![self]);
994
if has_mut_self {
995
input.parse::<Token![mut]>()?;
996
}
997
998
let mut has_self = false;
999
let mut name = if (input.peek(Ident) || input.peek(Token![_]) || {
1000
has_self = allow_self && input.peek(Token![self]);
1001
has_self
1002
}) && input.peek2(Token![:])
1003
&& !input.peek2(Token![::])
1004
{
1005
let name = input.call(Ident::parse_any)?;
1006
let colon: Token![:] = input.parse()?;
1007
Some((name, colon))
1008
} else {
1009
has_self = false;
1010
None
1011
};
1012
1013
let ty = if allow_self && !has_self && input.peek(Token![mut]) && input.peek2(Token![self])
1014
{
1015
input.parse::<Token![mut]>()?;
1016
input.parse::<Token![self]>()?;
1017
None
1018
} else if has_mut_self && name.is_none() {
1019
input.parse::<Token![self]>()?;
1020
None
1021
} else {
1022
Some(input.parse()?)
1023
};
1024
1025
let ty = match ty {
1026
Some(ty) if !has_mut_self => ty,
1027
_ => {
1028
name = None;
1029
Type::Verbatim(verbatim::between(&begin, input))
1030
}
1031
};
1032
1033
Ok(BareFnArg { attrs, name, ty })
1034
}
1035
1036
fn parse_bare_variadic(input: ParseStream, attrs: Vec<Attribute>) -> Result<BareVariadic> {
1037
Ok(BareVariadic {
1038
attrs,
1039
name: if input.peek(Ident) || input.peek(Token![_]) {
1040
let name = input.call(Ident::parse_any)?;
1041
let colon: Token![:] = input.parse()?;
1042
Some((name, colon))
1043
} else {
1044
None
1045
},
1046
dots: input.parse()?,
1047
comma: input.parse()?,
1048
})
1049
}
1050
1051
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1052
impl Parse for Abi {
1053
fn parse(input: ParseStream) -> Result<Self> {
1054
Ok(Abi {
1055
extern_token: input.parse()?,
1056
name: input.parse()?,
1057
})
1058
}
1059
}
1060
1061
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
1062
impl Parse for Option<Abi> {
1063
fn parse(input: ParseStream) -> Result<Self> {
1064
if input.peek(Token![extern]) {
1065
input.parse().map(Some)
1066
} else {
1067
Ok(None)
1068
}
1069
}
1070
}
1071
}
1072
1073
#[cfg(feature = "printing")]
1074
mod printing {
1075
use crate::attr::FilterAttrs;
1076
use crate::path;
1077
use crate::path::printing::PathStyle;
1078
use crate::print::TokensOrDefault;
1079
use crate::ty::{
1080
Abi, BareFnArg, BareVariadic, ReturnType, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait,
1081
TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice,
1082
TypeTraitObject, TypeTuple,
1083
};
1084
use proc_macro2::TokenStream;
1085
use quote::{ToTokens, TokenStreamExt};
1086
1087
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1088
impl ToTokens for TypeSlice {
1089
fn to_tokens(&self, tokens: &mut TokenStream) {
1090
self.bracket_token.surround(tokens, |tokens| {
1091
self.elem.to_tokens(tokens);
1092
});
1093
}
1094
}
1095
1096
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1097
impl ToTokens for TypeArray {
1098
fn to_tokens(&self, tokens: &mut TokenStream) {
1099
self.bracket_token.surround(tokens, |tokens| {
1100
self.elem.to_tokens(tokens);
1101
self.semi_token.to_tokens(tokens);
1102
self.len.to_tokens(tokens);
1103
});
1104
}
1105
}
1106
1107
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1108
impl ToTokens for TypePtr {
1109
fn to_tokens(&self, tokens: &mut TokenStream) {
1110
self.star_token.to_tokens(tokens);
1111
match &self.mutability {
1112
Some(tok) => tok.to_tokens(tokens),
1113
None => {
1114
TokensOrDefault(&self.const_token).to_tokens(tokens);
1115
}
1116
}
1117
self.elem.to_tokens(tokens);
1118
}
1119
}
1120
1121
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1122
impl ToTokens for TypeReference {
1123
fn to_tokens(&self, tokens: &mut TokenStream) {
1124
self.and_token.to_tokens(tokens);
1125
self.lifetime.to_tokens(tokens);
1126
self.mutability.to_tokens(tokens);
1127
self.elem.to_tokens(tokens);
1128
}
1129
}
1130
1131
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1132
impl ToTokens for TypeBareFn {
1133
fn to_tokens(&self, tokens: &mut TokenStream) {
1134
self.lifetimes.to_tokens(tokens);
1135
self.unsafety.to_tokens(tokens);
1136
self.abi.to_tokens(tokens);
1137
self.fn_token.to_tokens(tokens);
1138
self.paren_token.surround(tokens, |tokens| {
1139
self.inputs.to_tokens(tokens);
1140
if let Some(variadic) = &self.variadic {
1141
if !self.inputs.empty_or_trailing() {
1142
let span = variadic.dots.spans[0];
1143
Token![,](span).to_tokens(tokens);
1144
}
1145
variadic.to_tokens(tokens);
1146
}
1147
});
1148
self.output.to_tokens(tokens);
1149
}
1150
}
1151
1152
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1153
impl ToTokens for TypeNever {
1154
fn to_tokens(&self, tokens: &mut TokenStream) {
1155
self.bang_token.to_tokens(tokens);
1156
}
1157
}
1158
1159
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1160
impl ToTokens for TypeTuple {
1161
fn to_tokens(&self, tokens: &mut TokenStream) {
1162
self.paren_token.surround(tokens, |tokens| {
1163
self.elems.to_tokens(tokens);
1164
// If we only have one argument, we need a trailing comma to
1165
// distinguish TypeTuple from TypeParen.
1166
if self.elems.len() == 1 && !self.elems.trailing_punct() {
1167
<Token![,]>::default().to_tokens(tokens);
1168
}
1169
});
1170
}
1171
}
1172
1173
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1174
impl ToTokens for TypePath {
1175
fn to_tokens(&self, tokens: &mut TokenStream) {
1176
path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::AsWritten);
1177
}
1178
}
1179
1180
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1181
impl ToTokens for TypeTraitObject {
1182
fn to_tokens(&self, tokens: &mut TokenStream) {
1183
self.dyn_token.to_tokens(tokens);
1184
self.bounds.to_tokens(tokens);
1185
}
1186
}
1187
1188
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1189
impl ToTokens for TypeImplTrait {
1190
fn to_tokens(&self, tokens: &mut TokenStream) {
1191
self.impl_token.to_tokens(tokens);
1192
self.bounds.to_tokens(tokens);
1193
}
1194
}
1195
1196
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1197
impl ToTokens for TypeGroup {
1198
fn to_tokens(&self, tokens: &mut TokenStream) {
1199
self.group_token.surround(tokens, |tokens| {
1200
self.elem.to_tokens(tokens);
1201
});
1202
}
1203
}
1204
1205
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1206
impl ToTokens for TypeParen {
1207
fn to_tokens(&self, tokens: &mut TokenStream) {
1208
self.paren_token.surround(tokens, |tokens| {
1209
self.elem.to_tokens(tokens);
1210
});
1211
}
1212
}
1213
1214
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1215
impl ToTokens for TypeInfer {
1216
fn to_tokens(&self, tokens: &mut TokenStream) {
1217
self.underscore_token.to_tokens(tokens);
1218
}
1219
}
1220
1221
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1222
impl ToTokens for TypeMacro {
1223
fn to_tokens(&self, tokens: &mut TokenStream) {
1224
self.mac.to_tokens(tokens);
1225
}
1226
}
1227
1228
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1229
impl ToTokens for ReturnType {
1230
fn to_tokens(&self, tokens: &mut TokenStream) {
1231
match self {
1232
ReturnType::Default => {}
1233
ReturnType::Type(arrow, ty) => {
1234
arrow.to_tokens(tokens);
1235
ty.to_tokens(tokens);
1236
}
1237
}
1238
}
1239
}
1240
1241
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1242
impl ToTokens for BareFnArg {
1243
fn to_tokens(&self, tokens: &mut TokenStream) {
1244
tokens.append_all(self.attrs.outer());
1245
if let Some((name, colon)) = &self.name {
1246
name.to_tokens(tokens);
1247
colon.to_tokens(tokens);
1248
}
1249
self.ty.to_tokens(tokens);
1250
}
1251
}
1252
1253
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1254
impl ToTokens for BareVariadic {
1255
fn to_tokens(&self, tokens: &mut TokenStream) {
1256
tokens.append_all(self.attrs.outer());
1257
if let Some((name, colon)) = &self.name {
1258
name.to_tokens(tokens);
1259
colon.to_tokens(tokens);
1260
}
1261
self.dots.to_tokens(tokens);
1262
self.comma.to_tokens(tokens);
1263
}
1264
}
1265
1266
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1267
impl ToTokens for Abi {
1268
fn to_tokens(&self, tokens: &mut TokenStream) {
1269
self.extern_token.to_tokens(tokens);
1270
self.name.to_tokens(tokens);
1271
}
1272
}
1273
}
1274
1275