about summary refs log tree commit diff
path: root/library/proc_macro
diff options
context:
space:
mode:
authorAsuna <SpriteOvO@gmail.com>2024-10-09 18:29:31 +0800
committerAsuna <SpriteOvO@gmail.com>2024-10-27 03:17:05 +0100
commit42fbaf1ddde7c334ded228eff6e5fa31aff8fb94 (patch)
treed6827e5beb65d76f5bd6faba368b78638b9e7ff4 /library/proc_macro
parent4dce9138d7318d061d0560b299c295aa7c240295 (diff)
downloadrust-42fbaf1ddde7c334ded228eff6e5fa31aff8fb94.tar.gz
rust-42fbaf1ddde7c334ded228eff6e5fa31aff8fb94.zip
Add a new trait `proc_macro::ToTokens`
Diffstat (limited to 'library/proc_macro')
-rw-r--r--library/proc_macro/src/lib.rs4
-rw-r--r--library/proc_macro/src/to_tokens.rs310
2 files changed, 314 insertions, 0 deletions
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index ae47bb7adf4..15770248b31 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -32,6 +32,7 @@
 #![feature(restricted_std)]
 #![feature(rustc_attrs)]
 #![feature(min_specialization)]
+#![feature(extend_one)]
 #![recursion_limit = "256"]
 #![allow(internal_features)]
 #![deny(ffi_unwind_calls)]
@@ -43,6 +44,7 @@ pub mod bridge;
 
 mod diagnostic;
 mod escape;
+mod to_tokens;
 
 use std::ffi::CStr;
 use std::ops::{Range, RangeBounds};
@@ -52,6 +54,8 @@ use std::{error, fmt};
 
 #[unstable(feature = "proc_macro_diagnostic", issue = "54140")]
 pub use diagnostic::{Diagnostic, Level, MultiSpan};
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+pub use to_tokens::ToTokens;
 
 use crate::escape::{EscapeOptions, escape_bytes};
 
diff --git a/library/proc_macro/src/to_tokens.rs b/library/proc_macro/src/to_tokens.rs
new file mode 100644
index 00000000000..8f697b416d5
--- /dev/null
+++ b/library/proc_macro/src/to_tokens.rs
@@ -0,0 +1,310 @@
+use std::borrow::Cow;
+use std::ffi::{CStr, CString};
+use std::rc::Rc;
+
+use crate::{ConcatTreesHelper, Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
+
+/// Types that can be interpolated inside a [`quote!`] invocation.
+///
+/// [`quote!`]: crate::quote!
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+pub trait ToTokens {
+    /// Write `self` to the given `TokenStream`.
+    ///
+    /// # Example
+    ///
+    /// Example implementation for a struct representing Rust paths like
+    /// `std::cmp::PartialEq`:
+    ///
+    /// ```
+    /// #![feature(proc_macro_totokens)]
+    ///
+    /// use std::iter;
+    /// use proc_macro::{Spacing, Punct, TokenStream, TokenTree, ToTokens};
+    ///
+    /// pub struct Path {
+    ///     pub global: bool,
+    ///     pub segments: Vec<PathSegment>,
+    /// }
+    ///
+    /// impl ToTokens for Path {
+    ///     fn to_tokens(&self, tokens: &mut TokenStream) {
+    ///         for (i, segment) in self.segments.iter().enumerate() {
+    ///             if i > 0 || self.global {
+    ///                 // Double colon `::`
+    ///                 tokens.extend(iter::once(TokenTree::from(Punct::new(':', Spacing::Joint))));
+    ///                 tokens.extend(iter::once(TokenTree::from(Punct::new(':', Spacing::Alone))));
+    ///             }
+    ///             segment.to_tokens(tokens);
+    ///         }
+    ///     }
+    /// }
+    /// #
+    /// # pub struct PathSegment;
+    /// #
+    /// # impl ToTokens for PathSegment {
+    /// #     fn to_tokens(&self, tokens: &mut TokenStream) {
+    /// #         unimplemented!()
+    /// #     }
+    /// # }
+    /// ```
+    fn to_tokens(&self, tokens: &mut TokenStream);
+
+    /// Convert `self` directly into a `TokenStream` object.
+    ///
+    /// This method is implicitly implemented using `to_tokens`, and acts as a
+    /// convenience method for consumers of the `ToTokens` trait.
+    fn to_token_stream(&self) -> TokenStream {
+        let mut tokens = TokenStream::new();
+        self.to_tokens(&mut tokens);
+        tokens
+    }
+
+    /// Convert `self` directly into a `TokenStream` object.
+    ///
+    /// This method is implicitly implemented using `to_tokens`, and acts as a
+    /// convenience method for consumers of the `ToTokens` trait.
+    fn into_token_stream(self) -> TokenStream
+    where
+        Self: Sized,
+    {
+        self.to_token_stream()
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for TokenTree {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(self.clone());
+    }
+
+    fn into_token_stream(self) -> TokenStream {
+        let mut builder = ConcatTreesHelper::new(1);
+        builder.push(self);
+        builder.build()
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for TokenStream {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend(self.clone());
+    }
+
+    fn into_token_stream(self) -> TokenStream {
+        self
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for Literal {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(TokenTree::from(self.clone()));
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for Ident {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(TokenTree::from(self.clone()));
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for Punct {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(TokenTree::from(self.clone()));
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for Group {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        tokens.extend_one(TokenTree::from(self.clone()));
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ?Sized> ToTokens for &T {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ?Sized> ToTokens for &mut T {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ?Sized> ToTokens for Box<T> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ?Sized> ToTokens for Rc<T> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens + ToOwned + ?Sized> ToTokens for Cow<'_, T> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        (**self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl<T: ToTokens> ToTokens for Option<T> {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        if let Some(t) = self {
+            t.to_tokens(tokens);
+        }
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u8 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u8_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u16 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u16_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u32 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u32_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u64 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u64_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for u128 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::u128_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i8 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i8_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i16 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i16_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i32 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i32_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i64 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i64_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for i128 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::i128_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for f32 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::f32_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for f64 {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::f64_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for usize {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::usize_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for isize {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::isize_suffixed(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for bool {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        let word = if *self { "true" } else { "false" };
+        Ident::new(word, Span::call_site()).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for char {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::character(*self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for str {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::string(self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for String {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::string(self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for CStr {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::c_string(self).to_tokens(tokens)
+    }
+}
+
+#[unstable(feature = "proc_macro_totokens", issue = "130977")]
+impl ToTokens for CString {
+    fn to_tokens(&self, tokens: &mut TokenStream) {
+        Literal::c_string(self).to_tokens(tokens)
+    }
+}