| 1 | |
| 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 | |
| 19 | |
| 20 | |
| 21 | |
| 22 | |
| 23 | |
| 24 | |
| 25 | |
| 26 | |
| 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 | |
| 38 | |
| 39 | |
| 40 | |
| 41 | |
| 42 | |
| 43 | |
| 44 | |
| 45 | #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
|
| 46 | pub enum GenericParam {
|
| 47 | |
| 48 | Lifetime(LifetimeParam),
|
| 49 |
|
| 50 | |
| 51 | Type(TypeParam),
|
| 52 |
|
| 53 | |
| 54 | Const(ConstParam),
|
| 55 | }
|
| 56 | }
|
| 57 |
|
| 58 | ast_struct! {
|
| 59 | |
| 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 | |
| 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 | |
| 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 | |
| 110 | pub fn lifetimes(&self) -> impl Iterator<Item = &LifetimeParam> [Lifetimes] {
|
| 111 | Lifetimes(self.params.iter())
|
| 112 | }
|
| 113 | }
|
| 114 |
|
| 115 | return_impl_trait! {
|
| 116 | |
| 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 | |
| 124 | pub fn type_params(&self) -> impl Iterator<Item = &TypeParam> [TypeParams] {
|
| 125 | TypeParams(self.params.iter())
|
| 126 | }
|
| 127 | }
|
| 128 |
|
| 129 | return_impl_trait! {
|
| 130 | |
| 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 | |
| 138 | pub fn const_params(&self) -> impl Iterator<Item = &ConstParam> [ConstParams] {
|
| 139 | ConstParams(self.params.iter())
|
| 140 | }
|
| 141 | }
|
| 142 |
|
| 143 | return_impl_trait! {
|
| 144 | |
| 145 | pub fn const_params_mut(&mut self) -> impl Iterator<Item = &mut ConstParam> [ConstParamsMut] {
|
| 146 | ConstParamsMut(self.params.iter_mut())
|
| 147 | }
|
| 148 | }
|
| 149 |
|
| 150 | |
| 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 | |
| 159 | |
| 160 | |
| 161 | |
| 162 | |
| 163 | |
| 164 | |
| 165 | |
| 166 | |
| 167 | |
| 168 | |
| 169 | |
| 170 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 349 | pub fn as_turbofish(&self) -> Turbofish<'a> {
|
| 350 | Turbofish(self.0)
|
| 351 | }
|
| 352 | }
|
| 353 |
|
| 354 | ast_struct! {
|
| 355 | |
| 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 | |
| 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 | |
| 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 | |
| 419 | pub lifetimes: Option<BoundLifetimes>,
|
| 420 | |
| 421 | pub path: Path,
|
| 422 | }
|
| 423 | }
|
| 424 |
|
| 425 | ast_enum! {
|
| 426 | |
| 427 | |
| 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 | |
| 437 | |
| 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 | |
| 450 | #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
|
| 451 | #[non_exhaustive]
|
| 452 | pub enum CapturedParam {
|
| 453 | |
| 454 | |
| 455 | Lifetime(Lifetime),
|
| 456 | |
| 457 | |
| 458 | |
| 459 | Ident(Ident),
|
| 460 | }
|
| 461 | }
|
| 462 |
|
| 463 | ast_struct! {
|
| 464 | |
| 465 | |
| 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 | |
| 475 | |
| 476 | |
| 477 | |
| 478 | |
| 479 | |
| 480 | |
| 481 | #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
|
| 482 | #[non_exhaustive]
|
| 483 | pub enum WherePredicate {
|
| 484 | |
| 485 | Lifetime(PredicateLifetime),
|
| 486 |
|
| 487 | |
| 488 | Type(PredicateType),
|
| 489 | }
|
| 490 | }
|
| 491 |
|
| 492 | ast_struct! {
|
| 493 | |
| 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 | |
| 504 | #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
|
| 505 | pub struct PredicateType {
|
| 506 | |
| 507 | pub lifetimes: Option<BoundLifetimes>,
|
| 508 | |
| 509 | pub bounded_ty: Type,
|
| 510 | pub colon_token: Token![:],
|
| 511 | |
| 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 | |
| 1101 | |
| 1102 | |
| 1103 | |
| 1104 | |
| 1105 | |
| 1106 | |
| 1107 | |
| 1108 | |
| 1109 | |
| 1110 | |
| 1111 | |
| 1112 | |
| 1113 | |
| 1114 | |
| 1115 | |
| 1116 | |
| 1117 | |
| 1118 | |
| 1119 | |
| 1120 | |
| 1121 | |
| 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(); |
| 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 | |
| 1171 | |
| 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 | |
| 1205 | |
| 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 | |
| 1225 | tokens.append_all(param.attrs.outer());
|
| 1226 | param.ident.to_tokens(tokens);
|
| 1227 | if !param.bounds.is_empty() {
|
| 1228 | TokensOrDefault(¶m.colon_token).to_tokens(tokens);
|
| 1229 | param.bounds.to_tokens(tokens);
|
| 1230 | }
|
| 1231 | }
|
| 1232 | GenericParam::Const(param) => {
|
| 1233 | |
| 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 | |
| 1257 | |
| 1258 | let mut trailing_or_empty = true;
|
| 1259 | for param in self.0.params.pairs() {
|
| 1260 | if let GenericParam::Lifetime(def) = *param.value() {
|
| 1261 | |
| 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 | |
| 1279 | param.ident.to_tokens(tokens);
|
| 1280 | }
|
| 1281 | GenericParam::Const(param) => {
|
| 1282 | |
| 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 | |
| 1417 | |
| 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 | |
| 1469 | |
| 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 | }
|