diff options
| author | Asuna <SpriteOvO@gmail.com> | 2024-10-09 18:29:31 +0800 |
|---|---|---|
| committer | Asuna <SpriteOvO@gmail.com> | 2024-10-27 03:17:05 +0100 |
| commit | 42fbaf1ddde7c334ded228eff6e5fa31aff8fb94 (patch) | |
| tree | d6827e5beb65d76f5bd6faba368b78638b9e7ff4 /library/proc_macro | |
| parent | 4dce9138d7318d061d0560b299c295aa7c240295 (diff) | |
| download | rust-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.rs | 4 | ||||
| -rw-r--r-- | library/proc_macro/src/to_tokens.rs | 310 |
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) + } +} |
