runtime.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. use self::get_span::{GetSpan, GetSpanBase, GetSpanInner};
  3. use crate::{IdentFragment, ToTokens, TokenStreamExt};
  4. use core::fmt;
  5. use core::iter;
  6. use core::ops::BitOr;
  7. use proc_macro2::{Group, Ident, Punct, Spacing, TokenTree};
  8. #[doc(hidden)]
  9. pub use alloc::format;
  10. #[doc(hidden)]
  11. pub use core::option::Option;
  12. #[doc(hidden)]
  13. pub type Delimiter = proc_macro2::Delimiter;
  14. #[doc(hidden)]
  15. pub type Span = proc_macro2::Span;
  16. #[doc(hidden)]
  17. pub type TokenStream = proc_macro2::TokenStream;
  18. #[doc(hidden)]
  19. pub struct HasIterator; // True
  20. #[doc(hidden)]
  21. pub struct ThereIsNoIteratorInRepetition; // False
  22. impl BitOr<ThereIsNoIteratorInRepetition> for ThereIsNoIteratorInRepetition {
  23. type Output = ThereIsNoIteratorInRepetition;
  24. fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> ThereIsNoIteratorInRepetition {
  25. ThereIsNoIteratorInRepetition
  26. }
  27. }
  28. impl BitOr<ThereIsNoIteratorInRepetition> for HasIterator {
  29. type Output = HasIterator;
  30. fn bitor(self, _rhs: ThereIsNoIteratorInRepetition) -> HasIterator {
  31. HasIterator
  32. }
  33. }
  34. impl BitOr<HasIterator> for ThereIsNoIteratorInRepetition {
  35. type Output = HasIterator;
  36. fn bitor(self, _rhs: HasIterator) -> HasIterator {
  37. HasIterator
  38. }
  39. }
  40. impl BitOr<HasIterator> for HasIterator {
  41. type Output = HasIterator;
  42. fn bitor(self, _rhs: HasIterator) -> HasIterator {
  43. HasIterator
  44. }
  45. }
  46. /// Extension traits used by the implementation of `quote!`. These are defined
  47. /// in separate traits, rather than as a single trait due to ambiguity issues.
  48. ///
  49. /// These traits expose a `quote_into_iter` method which should allow calling
  50. /// whichever impl happens to be applicable. Calling that method repeatedly on
  51. /// the returned value should be idempotent.
  52. #[doc(hidden)]
  53. pub mod ext {
  54. use super::RepInterp;
  55. use super::{HasIterator as HasIter, ThereIsNoIteratorInRepetition as DoesNotHaveIter};
  56. use crate::ToTokens;
  57. use alloc::collections::btree_set::{self, BTreeSet};
  58. use core::slice;
  59. /// Extension trait providing the `quote_into_iter` method on iterators.
  60. #[doc(hidden)]
  61. pub trait RepIteratorExt: Iterator + Sized {
  62. fn quote_into_iter(self) -> (Self, HasIter) {
  63. (self, HasIter)
  64. }
  65. }
  66. impl<T: Iterator> RepIteratorExt for T {}
  67. /// Extension trait providing the `quote_into_iter` method for
  68. /// non-iterable types. These types interpolate the same value in each
  69. /// iteration of the repetition.
  70. #[doc(hidden)]
  71. pub trait RepToTokensExt {
  72. /// Pretend to be an iterator for the purposes of `quote_into_iter`.
  73. /// This allows repeated calls to `quote_into_iter` to continue
  74. /// correctly returning DoesNotHaveIter.
  75. fn next(&self) -> Option<&Self> {
  76. Some(self)
  77. }
  78. fn quote_into_iter(&self) -> (&Self, DoesNotHaveIter) {
  79. (self, DoesNotHaveIter)
  80. }
  81. }
  82. impl<T: ToTokens + ?Sized> RepToTokensExt for T {}
  83. /// Extension trait providing the `quote_into_iter` method for types that
  84. /// can be referenced as an iterator.
  85. #[doc(hidden)]
  86. pub trait RepAsIteratorExt<'q> {
  87. type Iter: Iterator;
  88. fn quote_into_iter(&'q self) -> (Self::Iter, HasIter);
  89. }
  90. impl<'q, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &T {
  91. type Iter = T::Iter;
  92. fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
  93. <T as RepAsIteratorExt>::quote_into_iter(*self)
  94. }
  95. }
  96. impl<'q, T: RepAsIteratorExt<'q> + ?Sized> RepAsIteratorExt<'q> for &mut T {
  97. type Iter = T::Iter;
  98. fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
  99. <T as RepAsIteratorExt>::quote_into_iter(*self)
  100. }
  101. }
  102. impl<'q, T: 'q> RepAsIteratorExt<'q> for [T] {
  103. type Iter = slice::Iter<'q, T>;
  104. fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
  105. (self.iter(), HasIter)
  106. }
  107. }
  108. impl<'q, T: 'q, const N: usize> RepAsIteratorExt<'q> for [T; N] {
  109. type Iter = slice::Iter<'q, T>;
  110. fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
  111. (self.iter(), HasIter)
  112. }
  113. }
  114. impl<'q, T: 'q> RepAsIteratorExt<'q> for Vec<T> {
  115. type Iter = slice::Iter<'q, T>;
  116. fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
  117. (self.iter(), HasIter)
  118. }
  119. }
  120. impl<'q, T: 'q> RepAsIteratorExt<'q> for BTreeSet<T> {
  121. type Iter = btree_set::Iter<'q, T>;
  122. fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
  123. (self.iter(), HasIter)
  124. }
  125. }
  126. impl<'q, T: RepAsIteratorExt<'q>> RepAsIteratorExt<'q> for RepInterp<T> {
  127. type Iter = T::Iter;
  128. fn quote_into_iter(&'q self) -> (Self::Iter, HasIter) {
  129. self.0.quote_into_iter()
  130. }
  131. }
  132. }
  133. // Helper type used within interpolations to allow for repeated binding names.
  134. // Implements the relevant traits, and exports a dummy `next()` method.
  135. #[derive(Copy, Clone)]
  136. #[doc(hidden)]
  137. pub struct RepInterp<T>(pub T);
  138. impl<T> RepInterp<T> {
  139. // This method is intended to look like `Iterator::next`, and is called when
  140. // a name is bound multiple times, as the previous binding will shadow the
  141. // original `Iterator` object. This allows us to avoid advancing the
  142. // iterator multiple times per iteration.
  143. pub fn next(self) -> Option<T> {
  144. Some(self.0)
  145. }
  146. }
  147. impl<T: Iterator> Iterator for RepInterp<T> {
  148. type Item = T::Item;
  149. fn next(&mut self) -> Option<Self::Item> {
  150. self.0.next()
  151. }
  152. }
  153. impl<T: ToTokens> ToTokens for RepInterp<T> {
  154. fn to_tokens(&self, tokens: &mut TokenStream) {
  155. self.0.to_tokens(tokens);
  156. }
  157. }
  158. #[doc(hidden)]
  159. #[inline]
  160. pub fn get_span<T>(span: T) -> GetSpan<T> {
  161. GetSpan(GetSpanInner(GetSpanBase(span)))
  162. }
  163. mod get_span {
  164. use core::ops::Deref;
  165. use proc_macro2::extra::DelimSpan;
  166. use proc_macro2::Span;
  167. pub struct GetSpan<T>(pub(crate) GetSpanInner<T>);
  168. pub struct GetSpanInner<T>(pub(crate) GetSpanBase<T>);
  169. pub struct GetSpanBase<T>(pub(crate) T);
  170. impl GetSpan<Span> {
  171. #[inline]
  172. pub fn __into_span(self) -> Span {
  173. ((self.0).0).0
  174. }
  175. }
  176. impl GetSpanInner<DelimSpan> {
  177. #[inline]
  178. pub fn __into_span(&self) -> Span {
  179. (self.0).0.join()
  180. }
  181. }
  182. impl<T> GetSpanBase<T> {
  183. #[allow(clippy::unused_self)]
  184. pub fn __into_span(&self) -> T {
  185. unreachable!()
  186. }
  187. }
  188. impl<T> Deref for GetSpan<T> {
  189. type Target = GetSpanInner<T>;
  190. #[inline]
  191. fn deref(&self) -> &Self::Target {
  192. &self.0
  193. }
  194. }
  195. impl<T> Deref for GetSpanInner<T> {
  196. type Target = GetSpanBase<T>;
  197. #[inline]
  198. fn deref(&self) -> &Self::Target {
  199. &self.0
  200. }
  201. }
  202. }
  203. #[doc(hidden)]
  204. pub fn push_group(tokens: &mut TokenStream, delimiter: Delimiter, inner: TokenStream) {
  205. tokens.append(Group::new(delimiter, inner));
  206. }
  207. #[doc(hidden)]
  208. pub fn push_group_spanned(
  209. tokens: &mut TokenStream,
  210. span: Span,
  211. delimiter: Delimiter,
  212. inner: TokenStream,
  213. ) {
  214. let mut g = Group::new(delimiter, inner);
  215. g.set_span(span);
  216. tokens.append(g);
  217. }
  218. #[doc(hidden)]
  219. pub fn parse(tokens: &mut TokenStream, s: &str) {
  220. let s: TokenStream = s.parse().expect("invalid token stream");
  221. tokens.extend(iter::once(s));
  222. }
  223. #[doc(hidden)]
  224. pub fn parse_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
  225. let s: TokenStream = s.parse().expect("invalid token stream");
  226. tokens.extend(s.into_iter().map(|t| respan_token_tree(t, span)));
  227. }
  228. // Token tree with every span replaced by the given one.
  229. fn respan_token_tree(mut token: TokenTree, span: Span) -> TokenTree {
  230. match &mut token {
  231. TokenTree::Group(g) => {
  232. let stream = g
  233. .stream()
  234. .into_iter()
  235. .map(|token| respan_token_tree(token, span))
  236. .collect();
  237. *g = Group::new(g.delimiter(), stream);
  238. g.set_span(span);
  239. }
  240. other => other.set_span(span),
  241. }
  242. token
  243. }
  244. #[doc(hidden)]
  245. pub fn push_ident(tokens: &mut TokenStream, s: &str) {
  246. let span = Span::call_site();
  247. push_ident_spanned(tokens, span, s);
  248. }
  249. #[doc(hidden)]
  250. pub fn push_ident_spanned(tokens: &mut TokenStream, span: Span, s: &str) {
  251. tokens.append(ident_maybe_raw(s, span));
  252. }
  253. #[doc(hidden)]
  254. pub fn push_lifetime(tokens: &mut TokenStream, lifetime: &str) {
  255. tokens.extend([
  256. TokenTree::Punct(Punct::new('\'', Spacing::Joint)),
  257. TokenTree::Ident(Ident::new(&lifetime[1..], Span::call_site())),
  258. ]);
  259. }
  260. #[doc(hidden)]
  261. pub fn push_lifetime_spanned(tokens: &mut TokenStream, span: Span, lifetime: &str) {
  262. tokens.extend([
  263. TokenTree::Punct({
  264. let mut apostrophe = Punct::new('\'', Spacing::Joint);
  265. apostrophe.set_span(span);
  266. apostrophe
  267. }),
  268. TokenTree::Ident(Ident::new(&lifetime[1..], span)),
  269. ]);
  270. }
  271. macro_rules! push_punct {
  272. ($name:ident $spanned:ident $char1:tt) => {
  273. #[doc(hidden)]
  274. pub fn $name(tokens: &mut TokenStream) {
  275. tokens.append(Punct::new($char1, Spacing::Alone));
  276. }
  277. #[doc(hidden)]
  278. pub fn $spanned(tokens: &mut TokenStream, span: Span) {
  279. let mut punct = Punct::new($char1, Spacing::Alone);
  280. punct.set_span(span);
  281. tokens.append(punct);
  282. }
  283. };
  284. ($name:ident $spanned:ident $char1:tt $char2:tt) => {
  285. #[doc(hidden)]
  286. pub fn $name(tokens: &mut TokenStream) {
  287. tokens.append(Punct::new($char1, Spacing::Joint));
  288. tokens.append(Punct::new($char2, Spacing::Alone));
  289. }
  290. #[doc(hidden)]
  291. pub fn $spanned(tokens: &mut TokenStream, span: Span) {
  292. let mut punct = Punct::new($char1, Spacing::Joint);
  293. punct.set_span(span);
  294. tokens.append(punct);
  295. let mut punct = Punct::new($char2, Spacing::Alone);
  296. punct.set_span(span);
  297. tokens.append(punct);
  298. }
  299. };
  300. ($name:ident $spanned:ident $char1:tt $char2:tt $char3:tt) => {
  301. #[doc(hidden)]
  302. pub fn $name(tokens: &mut TokenStream) {
  303. tokens.append(Punct::new($char1, Spacing::Joint));
  304. tokens.append(Punct::new($char2, Spacing::Joint));
  305. tokens.append(Punct::new($char3, Spacing::Alone));
  306. }
  307. #[doc(hidden)]
  308. pub fn $spanned(tokens: &mut TokenStream, span: Span) {
  309. let mut punct = Punct::new($char1, Spacing::Joint);
  310. punct.set_span(span);
  311. tokens.append(punct);
  312. let mut punct = Punct::new($char2, Spacing::Joint);
  313. punct.set_span(span);
  314. tokens.append(punct);
  315. let mut punct = Punct::new($char3, Spacing::Alone);
  316. punct.set_span(span);
  317. tokens.append(punct);
  318. }
  319. };
  320. }
  321. push_punct!(push_add push_add_spanned '+');
  322. push_punct!(push_add_eq push_add_eq_spanned '+' '=');
  323. push_punct!(push_and push_and_spanned '&');
  324. push_punct!(push_and_and push_and_and_spanned '&' '&');
  325. push_punct!(push_and_eq push_and_eq_spanned '&' '=');
  326. push_punct!(push_at push_at_spanned '@');
  327. push_punct!(push_bang push_bang_spanned '!');
  328. push_punct!(push_caret push_caret_spanned '^');
  329. push_punct!(push_caret_eq push_caret_eq_spanned '^' '=');
  330. push_punct!(push_colon push_colon_spanned ':');
  331. push_punct!(push_colon2 push_colon2_spanned ':' ':');
  332. push_punct!(push_comma push_comma_spanned ',');
  333. push_punct!(push_div push_div_spanned '/');
  334. push_punct!(push_div_eq push_div_eq_spanned '/' '=');
  335. push_punct!(push_dot push_dot_spanned '.');
  336. push_punct!(push_dot2 push_dot2_spanned '.' '.');
  337. push_punct!(push_dot3 push_dot3_spanned '.' '.' '.');
  338. push_punct!(push_dot_dot_eq push_dot_dot_eq_spanned '.' '.' '=');
  339. push_punct!(push_eq push_eq_spanned '=');
  340. push_punct!(push_eq_eq push_eq_eq_spanned '=' '=');
  341. push_punct!(push_ge push_ge_spanned '>' '=');
  342. push_punct!(push_gt push_gt_spanned '>');
  343. push_punct!(push_le push_le_spanned '<' '=');
  344. push_punct!(push_lt push_lt_spanned '<');
  345. push_punct!(push_mul_eq push_mul_eq_spanned '*' '=');
  346. push_punct!(push_ne push_ne_spanned '!' '=');
  347. push_punct!(push_or push_or_spanned '|');
  348. push_punct!(push_or_eq push_or_eq_spanned '|' '=');
  349. push_punct!(push_or_or push_or_or_spanned '|' '|');
  350. push_punct!(push_pound push_pound_spanned '#');
  351. push_punct!(push_question push_question_spanned '?');
  352. push_punct!(push_rarrow push_rarrow_spanned '-' '>');
  353. push_punct!(push_larrow push_larrow_spanned '<' '-');
  354. push_punct!(push_rem push_rem_spanned '%');
  355. push_punct!(push_rem_eq push_rem_eq_spanned '%' '=');
  356. push_punct!(push_fat_arrow push_fat_arrow_spanned '=' '>');
  357. push_punct!(push_semi push_semi_spanned ';');
  358. push_punct!(push_shl push_shl_spanned '<' '<');
  359. push_punct!(push_shl_eq push_shl_eq_spanned '<' '<' '=');
  360. push_punct!(push_shr push_shr_spanned '>' '>');
  361. push_punct!(push_shr_eq push_shr_eq_spanned '>' '>' '=');
  362. push_punct!(push_star push_star_spanned '*');
  363. push_punct!(push_sub push_sub_spanned '-');
  364. push_punct!(push_sub_eq push_sub_eq_spanned '-' '=');
  365. #[doc(hidden)]
  366. pub fn push_underscore(tokens: &mut TokenStream) {
  367. push_underscore_spanned(tokens, Span::call_site());
  368. }
  369. #[doc(hidden)]
  370. pub fn push_underscore_spanned(tokens: &mut TokenStream, span: Span) {
  371. tokens.append(Ident::new("_", span));
  372. }
  373. // Helper method for constructing identifiers from the `format_ident!` macro,
  374. // handling `r#` prefixes.
  375. #[doc(hidden)]
  376. pub fn mk_ident(id: &str, span: Option<Span>) -> Ident {
  377. let span = span.unwrap_or_else(Span::call_site);
  378. ident_maybe_raw(id, span)
  379. }
  380. fn ident_maybe_raw(id: &str, span: Span) -> Ident {
  381. if let Some(id) = id.strip_prefix("r#") {
  382. Ident::new_raw(id, span)
  383. } else {
  384. Ident::new(id, span)
  385. }
  386. }
  387. // Adapts from `IdentFragment` to `fmt::Display` for use by the `format_ident!`
  388. // macro, and exposes span information from these fragments.
  389. //
  390. // This struct also has forwarding implementations of the formatting traits
  391. // `Octal`, `LowerHex`, `UpperHex`, and `Binary` to allow for their use within
  392. // `format_ident!`.
  393. #[derive(Copy, Clone)]
  394. #[doc(hidden)]
  395. pub struct IdentFragmentAdapter<T: IdentFragment>(pub T);
  396. impl<T: IdentFragment> IdentFragmentAdapter<T> {
  397. pub fn span(&self) -> Option<Span> {
  398. self.0.span()
  399. }
  400. }
  401. impl<T: IdentFragment> fmt::Display for IdentFragmentAdapter<T> {
  402. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  403. IdentFragment::fmt(&self.0, f)
  404. }
  405. }
  406. impl<T: IdentFragment + fmt::Octal> fmt::Octal for IdentFragmentAdapter<T> {
  407. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  408. fmt::Octal::fmt(&self.0, f)
  409. }
  410. }
  411. impl<T: IdentFragment + fmt::LowerHex> fmt::LowerHex for IdentFragmentAdapter<T> {
  412. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  413. fmt::LowerHex::fmt(&self.0, f)
  414. }
  415. }
  416. impl<T: IdentFragment + fmt::UpperHex> fmt::UpperHex for IdentFragmentAdapter<T> {
  417. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  418. fmt::UpperHex::fmt(&self.0, f)
  419. }
  420. }
  421. impl<T: IdentFragment + fmt::Binary> fmt::Binary for IdentFragmentAdapter<T> {
  422. fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
  423. fmt::Binary::fmt(&self.0, f)
  424. }
  425. }