path.rs 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. #[cfg(feature = "parsing")]
  3. use crate::error::Result;
  4. use crate::expr::Expr;
  5. use crate::generics::TypeParamBound;
  6. use crate::ident::Ident;
  7. use crate::lifetime::Lifetime;
  8. use crate::punctuated::Punctuated;
  9. use crate::token;
  10. use crate::ty::{ReturnType, Type};
  11. ast_struct! {
  12. /// A path at which a named item is exported (e.g. `std::collections::HashMap`).
  13. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  14. pub struct Path {
  15. pub leading_colon: Option<Token![::]>,
  16. pub segments: Punctuated<PathSegment, Token![::]>,
  17. }
  18. }
  19. impl<T> From<T> for Path
  20. where
  21. T: Into<PathSegment>,
  22. {
  23. fn from(segment: T) -> Self {
  24. let mut path = Path {
  25. leading_colon: None,
  26. segments: Punctuated::new(),
  27. };
  28. path.segments.push_value(segment.into());
  29. path
  30. }
  31. }
  32. impl Path {
  33. /// Determines whether this is a path of length 1 equal to the given
  34. /// ident.
  35. ///
  36. /// For them to compare equal, it must be the case that:
  37. ///
  38. /// - the path has no leading colon,
  39. /// - the number of path segments is 1,
  40. /// - the first path segment has no angle bracketed or parenthesized
  41. /// path arguments, and
  42. /// - the ident of the first path segment is equal to the given one.
  43. ///
  44. /// # Example
  45. ///
  46. /// ```
  47. /// use proc_macro2::TokenStream;
  48. /// use syn::{Attribute, Error, Meta, Result};
  49. ///
  50. /// fn get_serde_meta_item(attr: &Attribute) -> Result<Option<&TokenStream>> {
  51. /// if attr.path().is_ident("serde") {
  52. /// match &attr.meta {
  53. /// Meta::List(meta) => Ok(Some(&meta.tokens)),
  54. /// bad => Err(Error::new_spanned(bad, "unrecognized attribute")),
  55. /// }
  56. /// } else {
  57. /// Ok(None)
  58. /// }
  59. /// }
  60. /// ```
  61. pub fn is_ident<I>(&self, ident: &I) -> bool
  62. where
  63. I: ?Sized,
  64. Ident: PartialEq<I>,
  65. {
  66. match self.get_ident() {
  67. Some(id) => id == ident,
  68. None => false,
  69. }
  70. }
  71. /// If this path consists of a single ident, returns the ident.
  72. ///
  73. /// A path is considered an ident if:
  74. ///
  75. /// - the path has no leading colon,
  76. /// - the number of path segments is 1, and
  77. /// - the first path segment has no angle bracketed or parenthesized
  78. /// path arguments.
  79. pub fn get_ident(&self) -> Option<&Ident> {
  80. if self.leading_colon.is_none()
  81. && self.segments.len() == 1
  82. && self.segments[0].arguments.is_none()
  83. {
  84. Some(&self.segments[0].ident)
  85. } else {
  86. None
  87. }
  88. }
  89. /// An error if this path is not a single ident, as defined in `get_ident`.
  90. #[cfg(feature = "parsing")]
  91. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  92. pub fn require_ident(&self) -> Result<&Ident> {
  93. self.get_ident().ok_or_else(|| {
  94. crate::error::new2(
  95. self.segments.first().unwrap().ident.span(),
  96. self.segments.last().unwrap().ident.span(),
  97. "expected this path to be an identifier",
  98. )
  99. })
  100. }
  101. }
  102. ast_struct! {
  103. /// A segment of a path together with any path arguments on that segment.
  104. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  105. pub struct PathSegment {
  106. pub ident: Ident,
  107. pub arguments: PathArguments,
  108. }
  109. }
  110. impl<T> From<T> for PathSegment
  111. where
  112. T: Into<Ident>,
  113. {
  114. fn from(ident: T) -> Self {
  115. PathSegment {
  116. ident: ident.into(),
  117. arguments: PathArguments::None,
  118. }
  119. }
  120. }
  121. ast_enum! {
  122. /// Angle bracketed or parenthesized arguments of a path segment.
  123. ///
  124. /// ## Angle bracketed
  125. ///
  126. /// The `<'a, T>` in `std::slice::iter<'a, T>`.
  127. ///
  128. /// ## Parenthesized
  129. ///
  130. /// The `(A, B) -> C` in `Fn(A, B) -> C`.
  131. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  132. pub enum PathArguments {
  133. None,
  134. /// The `<'a, T>` in `std::slice::iter<'a, T>`.
  135. AngleBracketed(AngleBracketedGenericArguments),
  136. /// The `(A, B) -> C` in `Fn(A, B) -> C`.
  137. Parenthesized(ParenthesizedGenericArguments),
  138. }
  139. }
  140. impl Default for PathArguments {
  141. fn default() -> Self {
  142. PathArguments::None
  143. }
  144. }
  145. impl PathArguments {
  146. pub fn is_empty(&self) -> bool {
  147. match self {
  148. PathArguments::None => true,
  149. PathArguments::AngleBracketed(bracketed) => bracketed.args.is_empty(),
  150. PathArguments::Parenthesized(_) => false,
  151. }
  152. }
  153. pub fn is_none(&self) -> bool {
  154. match self {
  155. PathArguments::None => true,
  156. PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false,
  157. }
  158. }
  159. }
  160. ast_enum! {
  161. /// An individual generic argument, like `'a`, `T`, or `Item = T`.
  162. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  163. #[non_exhaustive]
  164. pub enum GenericArgument {
  165. /// A lifetime argument.
  166. Lifetime(Lifetime),
  167. /// A type argument.
  168. Type(Type),
  169. /// A const expression. Must be inside of a block.
  170. ///
  171. /// NOTE: Identity expressions are represented as Type arguments, as
  172. /// they are indistinguishable syntactically.
  173. Const(Expr),
  174. /// A binding (equality constraint) on an associated type: the `Item =
  175. /// u8` in `Iterator<Item = u8>`.
  176. AssocType(AssocType),
  177. /// An equality constraint on an associated constant: the `PANIC =
  178. /// false` in `Trait<PANIC = false>`.
  179. AssocConst(AssocConst),
  180. /// An associated type bound: `Iterator<Item: Display>`.
  181. Constraint(Constraint),
  182. }
  183. }
  184. ast_struct! {
  185. /// Angle bracketed arguments of a path segment: the `<K, V>` in `HashMap<K,
  186. /// V>`.
  187. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  188. pub struct AngleBracketedGenericArguments {
  189. pub colon2_token: Option<Token![::]>,
  190. pub lt_token: Token![<],
  191. pub args: Punctuated<GenericArgument, Token![,]>,
  192. pub gt_token: Token![>],
  193. }
  194. }
  195. ast_struct! {
  196. /// A binding (equality constraint) on an associated type: the `Item = u8`
  197. /// in `Iterator<Item = u8>`.
  198. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  199. pub struct AssocType {
  200. pub ident: Ident,
  201. pub generics: Option<AngleBracketedGenericArguments>,
  202. pub eq_token: Token![=],
  203. pub ty: Type,
  204. }
  205. }
  206. ast_struct! {
  207. /// An equality constraint on an associated constant: the `PANIC = false` in
  208. /// `Trait<PANIC = false>`.
  209. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  210. pub struct AssocConst {
  211. pub ident: Ident,
  212. pub generics: Option<AngleBracketedGenericArguments>,
  213. pub eq_token: Token![=],
  214. pub value: Expr,
  215. }
  216. }
  217. ast_struct! {
  218. /// An associated type bound: `Iterator<Item: Display>`.
  219. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  220. pub struct Constraint {
  221. pub ident: Ident,
  222. pub generics: Option<AngleBracketedGenericArguments>,
  223. pub colon_token: Token![:],
  224. pub bounds: Punctuated<TypeParamBound, Token![+]>,
  225. }
  226. }
  227. ast_struct! {
  228. /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) ->
  229. /// C`.
  230. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  231. pub struct ParenthesizedGenericArguments {
  232. pub paren_token: token::Paren,
  233. /// `(A, B)`
  234. pub inputs: Punctuated<Type, Token![,]>,
  235. /// `C`
  236. pub output: ReturnType,
  237. }
  238. }
  239. ast_struct! {
  240. /// The explicit Self type in a qualified path: the `T` in `<T as
  241. /// Display>::fmt`.
  242. ///
  243. /// The actual path, including the trait and the associated item, is stored
  244. /// separately. The `position` field represents the index of the associated
  245. /// item qualified with this Self type.
  246. ///
  247. /// ```text
  248. /// <Vec<T> as a::b::Trait>::AssociatedItem
  249. /// ^~~~~~ ~~~~~~~~~~~~~~^
  250. /// ty position = 3
  251. ///
  252. /// <Vec<T>>::AssociatedItem
  253. /// ^~~~~~ ^
  254. /// ty position = 0
  255. /// ```
  256. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
  257. pub struct QSelf {
  258. pub lt_token: Token![<],
  259. pub ty: Box<Type>,
  260. pub position: usize,
  261. pub as_token: Option<Token![as]>,
  262. pub gt_token: Token![>],
  263. }
  264. }
  265. #[cfg(feature = "parsing")]
  266. pub(crate) mod parsing {
  267. use crate::error::Result;
  268. #[cfg(feature = "full")]
  269. use crate::expr::ExprBlock;
  270. use crate::expr::{Expr, ExprPath};
  271. use crate::ext::IdentExt as _;
  272. #[cfg(feature = "full")]
  273. use crate::generics::TypeParamBound;
  274. use crate::ident::Ident;
  275. use crate::lifetime::Lifetime;
  276. use crate::lit::Lit;
  277. use crate::parse::{Parse, ParseStream};
  278. #[cfg(feature = "full")]
  279. use crate::path::Constraint;
  280. use crate::path::{
  281. AngleBracketedGenericArguments, AssocConst, AssocType, GenericArgument,
  282. ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
  283. };
  284. use crate::punctuated::Punctuated;
  285. use crate::token;
  286. use crate::ty::{ReturnType, Type};
  287. #[cfg(not(feature = "full"))]
  288. use crate::verbatim;
  289. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  290. impl Parse for Path {
  291. fn parse(input: ParseStream) -> Result<Self> {
  292. Self::parse_helper(input, false)
  293. }
  294. }
  295. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  296. impl Parse for GenericArgument {
  297. fn parse(input: ParseStream) -> Result<Self> {
  298. if input.peek(Lifetime) && !input.peek2(Token![+]) {
  299. return Ok(GenericArgument::Lifetime(input.parse()?));
  300. }
  301. if input.peek(Lit) || input.peek(token::Brace) {
  302. return const_argument(input).map(GenericArgument::Const);
  303. }
  304. let mut argument: Type = input.parse()?;
  305. match argument {
  306. Type::Path(mut ty)
  307. if ty.qself.is_none()
  308. && ty.path.leading_colon.is_none()
  309. && ty.path.segments.len() == 1
  310. && match &ty.path.segments[0].arguments {
  311. PathArguments::None | PathArguments::AngleBracketed(_) => true,
  312. PathArguments::Parenthesized(_) => false,
  313. } =>
  314. {
  315. if let Some(eq_token) = input.parse::<Option<Token![=]>>()? {
  316. let segment = ty.path.segments.pop().unwrap().into_value();
  317. let ident = segment.ident;
  318. let generics = match segment.arguments {
  319. PathArguments::None => None,
  320. PathArguments::AngleBracketed(arguments) => Some(arguments),
  321. PathArguments::Parenthesized(_) => unreachable!(),
  322. };
  323. return if input.peek(Lit) || input.peek(token::Brace) {
  324. Ok(GenericArgument::AssocConst(AssocConst {
  325. ident,
  326. generics,
  327. eq_token,
  328. value: const_argument(input)?,
  329. }))
  330. } else {
  331. Ok(GenericArgument::AssocType(AssocType {
  332. ident,
  333. generics,
  334. eq_token,
  335. ty: input.parse()?,
  336. }))
  337. };
  338. }
  339. #[cfg(feature = "full")]
  340. if let Some(colon_token) = input.parse::<Option<Token![:]>>()? {
  341. let segment = ty.path.segments.pop().unwrap().into_value();
  342. return Ok(GenericArgument::Constraint(Constraint {
  343. ident: segment.ident,
  344. generics: match segment.arguments {
  345. PathArguments::None => None,
  346. PathArguments::AngleBracketed(arguments) => Some(arguments),
  347. PathArguments::Parenthesized(_) => unreachable!(),
  348. },
  349. colon_token,
  350. bounds: {
  351. let mut bounds = Punctuated::new();
  352. loop {
  353. if input.peek(Token![,]) || input.peek(Token![>]) {
  354. break;
  355. }
  356. bounds.push_value({
  357. let allow_precise_capture = false;
  358. let allow_const = true;
  359. TypeParamBound::parse_single(
  360. input,
  361. allow_precise_capture,
  362. allow_const,
  363. )?
  364. });
  365. if !input.peek(Token![+]) {
  366. break;
  367. }
  368. let punct: Token![+] = input.parse()?;
  369. bounds.push_punct(punct);
  370. }
  371. bounds
  372. },
  373. }));
  374. }
  375. argument = Type::Path(ty);
  376. }
  377. _ => {}
  378. }
  379. Ok(GenericArgument::Type(argument))
  380. }
  381. }
  382. pub(crate) fn const_argument(input: ParseStream) -> Result<Expr> {
  383. let lookahead = input.lookahead1();
  384. if input.peek(Lit) {
  385. let lit = input.parse()?;
  386. return Ok(Expr::Lit(lit));
  387. }
  388. if input.peek(Ident) {
  389. let ident: Ident = input.parse()?;
  390. return Ok(Expr::Path(ExprPath {
  391. attrs: Vec::new(),
  392. qself: None,
  393. path: Path::from(ident),
  394. }));
  395. }
  396. if input.peek(token::Brace) {
  397. #[cfg(feature = "full")]
  398. {
  399. let block: ExprBlock = input.parse()?;
  400. return Ok(Expr::Block(block));
  401. }
  402. #[cfg(not(feature = "full"))]
  403. {
  404. let begin = input.fork();
  405. let content;
  406. braced!(content in input);
  407. content.parse::<Expr>()?;
  408. let verbatim = verbatim::between(&begin, input);
  409. return Ok(Expr::Verbatim(verbatim));
  410. }
  411. }
  412. Err(lookahead.error())
  413. }
  414. impl AngleBracketedGenericArguments {
  415. /// Parse `::<…>` with mandatory leading `::`.
  416. ///
  417. /// The ordinary [`Parse`] impl for `AngleBracketedGenericArguments`
  418. /// parses optional leading `::`.
  419. #[cfg(feature = "full")]
  420. #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))]
  421. pub fn parse_turbofish(input: ParseStream) -> Result<Self> {
  422. let colon2_token: Token![::] = input.parse()?;
  423. Self::do_parse(Some(colon2_token), input)
  424. }
  425. pub(crate) fn do_parse(
  426. colon2_token: Option<Token![::]>,
  427. input: ParseStream,
  428. ) -> Result<Self> {
  429. Ok(AngleBracketedGenericArguments {
  430. colon2_token,
  431. lt_token: input.parse()?,
  432. args: {
  433. let mut args = Punctuated::new();
  434. loop {
  435. if input.peek(Token![>]) {
  436. break;
  437. }
  438. let value: GenericArgument = input.parse()?;
  439. args.push_value(value);
  440. if input.peek(Token![>]) {
  441. break;
  442. }
  443. let punct: Token![,] = input.parse()?;
  444. args.push_punct(punct);
  445. }
  446. args
  447. },
  448. gt_token: input.parse()?,
  449. })
  450. }
  451. }
  452. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  453. impl Parse for AngleBracketedGenericArguments {
  454. fn parse(input: ParseStream) -> Result<Self> {
  455. let colon2_token: Option<Token![::]> = input.parse()?;
  456. Self::do_parse(colon2_token, input)
  457. }
  458. }
  459. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  460. impl Parse for ParenthesizedGenericArguments {
  461. fn parse(input: ParseStream) -> Result<Self> {
  462. let content;
  463. Ok(ParenthesizedGenericArguments {
  464. paren_token: parenthesized!(content in input),
  465. inputs: content.parse_terminated(Type::parse, Token![,])?,
  466. output: input.call(ReturnType::without_plus)?,
  467. })
  468. }
  469. }
  470. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  471. impl Parse for PathSegment {
  472. fn parse(input: ParseStream) -> Result<Self> {
  473. Self::parse_helper(input, false)
  474. }
  475. }
  476. impl PathSegment {
  477. fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
  478. if input.peek(Token![super])
  479. || input.peek(Token![self])
  480. || input.peek(Token![crate])
  481. || cfg!(feature = "full") && input.peek(Token![try])
  482. {
  483. let ident = input.call(Ident::parse_any)?;
  484. return Ok(PathSegment::from(ident));
  485. }
  486. let ident = if input.peek(Token![Self]) {
  487. input.call(Ident::parse_any)?
  488. } else {
  489. input.parse()?
  490. };
  491. if !expr_style
  492. && input.peek(Token![<])
  493. && !input.peek(Token![<=])
  494. && !input.peek(Token![<<=])
  495. || input.peek(Token![::]) && input.peek3(Token![<])
  496. {
  497. Ok(PathSegment {
  498. ident,
  499. arguments: PathArguments::AngleBracketed(input.parse()?),
  500. })
  501. } else {
  502. Ok(PathSegment::from(ident))
  503. }
  504. }
  505. }
  506. impl Path {
  507. /// Parse a `Path` containing no path arguments on any of its segments.
  508. ///
  509. /// # Example
  510. ///
  511. /// ```
  512. /// use syn::{Path, Result, Token};
  513. /// use syn::parse::{Parse, ParseStream};
  514. ///
  515. /// // A simplified single `use` statement like:
  516. /// //
  517. /// // use std::collections::HashMap;
  518. /// //
  519. /// // Note that generic parameters are not allowed in a `use` statement
  520. /// // so the following must not be accepted.
  521. /// //
  522. /// // use a::<b>::c;
  523. /// struct SingleUse {
  524. /// use_token: Token![use],
  525. /// path: Path,
  526. /// }
  527. ///
  528. /// impl Parse for SingleUse {
  529. /// fn parse(input: ParseStream) -> Result<Self> {
  530. /// Ok(SingleUse {
  531. /// use_token: input.parse()?,
  532. /// path: input.call(Path::parse_mod_style)?,
  533. /// })
  534. /// }
  535. /// }
  536. /// ```
  537. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  538. pub fn parse_mod_style(input: ParseStream) -> Result<Self> {
  539. Ok(Path {
  540. leading_colon: input.parse()?,
  541. segments: {
  542. let mut segments = Punctuated::new();
  543. loop {
  544. if !input.peek(Ident)
  545. && !input.peek(Token![super])
  546. && !input.peek(Token![self])
  547. && !input.peek(Token![Self])
  548. && !input.peek(Token![crate])
  549. {
  550. break;
  551. }
  552. let ident = Ident::parse_any(input)?;
  553. segments.push_value(PathSegment::from(ident));
  554. if !input.peek(Token![::]) {
  555. break;
  556. }
  557. let punct = input.parse()?;
  558. segments.push_punct(punct);
  559. }
  560. if segments.is_empty() {
  561. return Err(input.parse::<Ident>().unwrap_err());
  562. } else if segments.trailing_punct() {
  563. return Err(input.error("expected path segment after `::`"));
  564. }
  565. segments
  566. },
  567. })
  568. }
  569. pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> {
  570. let mut path = Path {
  571. leading_colon: input.parse()?,
  572. segments: {
  573. let mut segments = Punctuated::new();
  574. let value = PathSegment::parse_helper(input, expr_style)?;
  575. segments.push_value(value);
  576. segments
  577. },
  578. };
  579. Path::parse_rest(input, &mut path, expr_style)?;
  580. Ok(path)
  581. }
  582. pub(crate) fn parse_rest(
  583. input: ParseStream,
  584. path: &mut Self,
  585. expr_style: bool,
  586. ) -> Result<()> {
  587. while input.peek(Token![::]) && !input.peek3(token::Paren) {
  588. let punct: Token![::] = input.parse()?;
  589. path.segments.push_punct(punct);
  590. let value = PathSegment::parse_helper(input, expr_style)?;
  591. path.segments.push_value(value);
  592. }
  593. Ok(())
  594. }
  595. pub(crate) fn is_mod_style(&self) -> bool {
  596. self.segments
  597. .iter()
  598. .all(|segment| segment.arguments.is_none())
  599. }
  600. }
  601. pub(crate) fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> {
  602. if input.peek(Token![<]) {
  603. let lt_token: Token![<] = input.parse()?;
  604. let this: Type = input.parse()?;
  605. let path = if input.peek(Token![as]) {
  606. let as_token: Token![as] = input.parse()?;
  607. let path: Path = input.parse()?;
  608. Some((as_token, path))
  609. } else {
  610. None
  611. };
  612. let gt_token: Token![>] = input.parse()?;
  613. let colon2_token: Token![::] = input.parse()?;
  614. let mut rest = Punctuated::new();
  615. loop {
  616. let path = PathSegment::parse_helper(input, expr_style)?;
  617. rest.push_value(path);
  618. if !input.peek(Token![::]) {
  619. break;
  620. }
  621. let punct: Token![::] = input.parse()?;
  622. rest.push_punct(punct);
  623. }
  624. let (position, as_token, path) = match path {
  625. Some((as_token, mut path)) => {
  626. let pos = path.segments.len();
  627. path.segments.push_punct(colon2_token);
  628. path.segments.extend(rest.into_pairs());
  629. (pos, Some(as_token), path)
  630. }
  631. None => {
  632. let path = Path {
  633. leading_colon: Some(colon2_token),
  634. segments: rest,
  635. };
  636. (0, None, path)
  637. }
  638. };
  639. let qself = QSelf {
  640. lt_token,
  641. ty: Box::new(this),
  642. position,
  643. as_token,
  644. gt_token,
  645. };
  646. Ok((Some(qself), path))
  647. } else {
  648. let path = Path::parse_helper(input, expr_style)?;
  649. Ok((None, path))
  650. }
  651. }
  652. }
  653. #[cfg(feature = "printing")]
  654. pub(crate) mod printing {
  655. use crate::generics;
  656. use crate::path::{
  657. AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument,
  658. ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
  659. };
  660. use crate::print::TokensOrDefault;
  661. #[cfg(feature = "parsing")]
  662. use crate::spanned::Spanned;
  663. #[cfg(feature = "parsing")]
  664. use proc_macro2::Span;
  665. use proc_macro2::TokenStream;
  666. use quote::ToTokens;
  667. use std::cmp;
  668. pub(crate) enum PathStyle {
  669. Expr,
  670. Mod,
  671. AsWritten,
  672. }
  673. impl Copy for PathStyle {}
  674. impl Clone for PathStyle {
  675. fn clone(&self) -> Self {
  676. *self
  677. }
  678. }
  679. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  680. impl ToTokens for Path {
  681. fn to_tokens(&self, tokens: &mut TokenStream) {
  682. print_path(tokens, self, PathStyle::AsWritten);
  683. }
  684. }
  685. pub(crate) fn print_path(tokens: &mut TokenStream, path: &Path, style: PathStyle) {
  686. path.leading_colon.to_tokens(tokens);
  687. for segment in path.segments.pairs() {
  688. print_path_segment(tokens, segment.value(), style);
  689. segment.punct().to_tokens(tokens);
  690. }
  691. }
  692. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  693. impl ToTokens for PathSegment {
  694. fn to_tokens(&self, tokens: &mut TokenStream) {
  695. print_path_segment(tokens, self, PathStyle::AsWritten);
  696. }
  697. }
  698. fn print_path_segment(tokens: &mut TokenStream, segment: &PathSegment, style: PathStyle) {
  699. segment.ident.to_tokens(tokens);
  700. print_path_arguments(tokens, &segment.arguments, style);
  701. }
  702. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  703. impl ToTokens for PathArguments {
  704. fn to_tokens(&self, tokens: &mut TokenStream) {
  705. print_path_arguments(tokens, self, PathStyle::AsWritten);
  706. }
  707. }
  708. fn print_path_arguments(tokens: &mut TokenStream, arguments: &PathArguments, style: PathStyle) {
  709. match arguments {
  710. PathArguments::None => {}
  711. PathArguments::AngleBracketed(arguments) => {
  712. print_angle_bracketed_generic_arguments(tokens, arguments, style);
  713. }
  714. PathArguments::Parenthesized(arguments) => {
  715. print_parenthesized_generic_arguments(tokens, arguments, style);
  716. }
  717. }
  718. }
  719. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  720. impl ToTokens for GenericArgument {
  721. #[allow(clippy::match_same_arms)]
  722. fn to_tokens(&self, tokens: &mut TokenStream) {
  723. match self {
  724. GenericArgument::Lifetime(lt) => lt.to_tokens(tokens),
  725. GenericArgument::Type(ty) => ty.to_tokens(tokens),
  726. GenericArgument::Const(expr) => {
  727. generics::printing::print_const_argument(expr, tokens);
  728. }
  729. GenericArgument::AssocType(assoc) => assoc.to_tokens(tokens),
  730. GenericArgument::AssocConst(assoc) => assoc.to_tokens(tokens),
  731. GenericArgument::Constraint(constraint) => constraint.to_tokens(tokens),
  732. }
  733. }
  734. }
  735. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  736. impl ToTokens for AngleBracketedGenericArguments {
  737. fn to_tokens(&self, tokens: &mut TokenStream) {
  738. print_angle_bracketed_generic_arguments(tokens, self, PathStyle::AsWritten);
  739. }
  740. }
  741. pub(crate) fn print_angle_bracketed_generic_arguments(
  742. tokens: &mut TokenStream,
  743. arguments: &AngleBracketedGenericArguments,
  744. style: PathStyle,
  745. ) {
  746. if let PathStyle::Mod = style {
  747. return;
  748. }
  749. conditionally_print_turbofish(tokens, &arguments.colon2_token, style);
  750. arguments.lt_token.to_tokens(tokens);
  751. // Print lifetimes before types/consts/bindings, regardless of their
  752. // order in args.
  753. let mut trailing_or_empty = true;
  754. for param in arguments.args.pairs() {
  755. match param.value() {
  756. GenericArgument::Lifetime(_) => {
  757. param.to_tokens(tokens);
  758. trailing_or_empty = param.punct().is_some();
  759. }
  760. GenericArgument::Type(_)
  761. | GenericArgument::Const(_)
  762. | GenericArgument::AssocType(_)
  763. | GenericArgument::AssocConst(_)
  764. | GenericArgument::Constraint(_) => {}
  765. }
  766. }
  767. for param in arguments.args.pairs() {
  768. match param.value() {
  769. GenericArgument::Type(_)
  770. | GenericArgument::Const(_)
  771. | GenericArgument::AssocType(_)
  772. | GenericArgument::AssocConst(_)
  773. | GenericArgument::Constraint(_) => {
  774. if !trailing_or_empty {
  775. <Token![,]>::default().to_tokens(tokens);
  776. }
  777. param.to_tokens(tokens);
  778. trailing_or_empty = param.punct().is_some();
  779. }
  780. GenericArgument::Lifetime(_) => {}
  781. }
  782. }
  783. arguments.gt_token.to_tokens(tokens);
  784. }
  785. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  786. impl ToTokens for AssocType {
  787. fn to_tokens(&self, tokens: &mut TokenStream) {
  788. self.ident.to_tokens(tokens);
  789. self.generics.to_tokens(tokens);
  790. self.eq_token.to_tokens(tokens);
  791. self.ty.to_tokens(tokens);
  792. }
  793. }
  794. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  795. impl ToTokens for AssocConst {
  796. fn to_tokens(&self, tokens: &mut TokenStream) {
  797. self.ident.to_tokens(tokens);
  798. self.generics.to_tokens(tokens);
  799. self.eq_token.to_tokens(tokens);
  800. generics::printing::print_const_argument(&self.value, tokens);
  801. }
  802. }
  803. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  804. impl ToTokens for Constraint {
  805. fn to_tokens(&self, tokens: &mut TokenStream) {
  806. self.ident.to_tokens(tokens);
  807. self.generics.to_tokens(tokens);
  808. self.colon_token.to_tokens(tokens);
  809. self.bounds.to_tokens(tokens);
  810. }
  811. }
  812. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  813. impl ToTokens for ParenthesizedGenericArguments {
  814. fn to_tokens(&self, tokens: &mut TokenStream) {
  815. print_parenthesized_generic_arguments(tokens, self, PathStyle::AsWritten);
  816. }
  817. }
  818. fn print_parenthesized_generic_arguments(
  819. tokens: &mut TokenStream,
  820. arguments: &ParenthesizedGenericArguments,
  821. style: PathStyle,
  822. ) {
  823. if let PathStyle::Mod = style {
  824. return;
  825. }
  826. conditionally_print_turbofish(tokens, &None, style);
  827. arguments.paren_token.surround(tokens, |tokens| {
  828. arguments.inputs.to_tokens(tokens);
  829. });
  830. arguments.output.to_tokens(tokens);
  831. }
  832. pub(crate) fn print_qpath(
  833. tokens: &mut TokenStream,
  834. qself: &Option<QSelf>,
  835. path: &Path,
  836. style: PathStyle,
  837. ) {
  838. let qself = match qself {
  839. Some(qself) => qself,
  840. None => {
  841. print_path(tokens, path, style);
  842. return;
  843. }
  844. };
  845. qself.lt_token.to_tokens(tokens);
  846. qself.ty.to_tokens(tokens);
  847. let pos = cmp::min(qself.position, path.segments.len());
  848. let mut segments = path.segments.pairs();
  849. if pos > 0 {
  850. TokensOrDefault(&qself.as_token).to_tokens(tokens);
  851. path.leading_colon.to_tokens(tokens);
  852. for (i, segment) in segments.by_ref().take(pos).enumerate() {
  853. print_path_segment(tokens, segment.value(), PathStyle::AsWritten);
  854. if i + 1 == pos {
  855. qself.gt_token.to_tokens(tokens);
  856. }
  857. segment.punct().to_tokens(tokens);
  858. }
  859. } else {
  860. qself.gt_token.to_tokens(tokens);
  861. path.leading_colon.to_tokens(tokens);
  862. }
  863. for segment in segments {
  864. print_path_segment(tokens, segment.value(), style);
  865. segment.punct().to_tokens(tokens);
  866. }
  867. }
  868. fn conditionally_print_turbofish(
  869. tokens: &mut TokenStream,
  870. colon2_token: &Option<Token![::]>,
  871. style: PathStyle,
  872. ) {
  873. match style {
  874. PathStyle::Expr => TokensOrDefault(colon2_token).to_tokens(tokens),
  875. PathStyle::Mod => unreachable!(),
  876. PathStyle::AsWritten => colon2_token.to_tokens(tokens),
  877. }
  878. }
  879. #[cfg(feature = "parsing")]
  880. #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))]
  881. impl Spanned for QSelf {
  882. fn span(&self) -> Span {
  883. struct QSelfDelimiters<'a>(&'a QSelf);
  884. impl<'a> ToTokens for QSelfDelimiters<'a> {
  885. fn to_tokens(&self, tokens: &mut TokenStream) {
  886. self.0.lt_token.to_tokens(tokens);
  887. self.0.gt_token.to_tokens(tokens);
  888. }
  889. }
  890. QSelfDelimiters(self).span()
  891. }
  892. }
  893. }