// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::detection::inside_proc_macro;use crate::fallback::{self, FromStr2 as _};#[cfg(span_locations)]use crate::location::LineColumn;#[cfg(proc_macro_span)]use crate::probe::proc_macro_span;#[cfg(all(span_locations, proc_macro_span_file))]use crate::probe::proc_macro_span_file;#[cfg(all(span_locations, proc_macro_span_location))]use crate::probe::proc_macro_span_location;use crate::{Delimiter, Punct, Spacing, TokenTree};use core::fmt::{self, Debug, Display};#[cfg(span_locations)]use core::ops::Range;use core::ops::RangeBounds;use std::ffi::CStr;#[cfg(span_locations)]use std::path::PathBuf; #[derive(Clone)]pub(crate) enum TokenStream { Compiler(DeferredTokenStream), Fallback(fallback::TokenStream),} // Work around https://github.com/rust-lang/rust/issues/65080.// In `impl Extend<TokenTree> for TokenStream` which is used heavily by quote,// we hold on to the appended tokens and do proc_macro::TokenStream::extend as// late as possible to batch together consecutive uses of the Extend impl.#[derive(Clone)]pub(crate) struct DeferredTokenStream { stream: proc_macro::TokenStream, extra: Vec<proc_macro::TokenTree>,} pub(crate) enum LexError { Compiler(proc_macro::LexError), Fallback(fallback::LexError), // Rustc was supposed to return a LexError, but it panicked instead. // https://github.com/rust-lang/rust/issues/58736 CompilerPanic,} #[cold]fn mismatch(line: u32) -> ! { #[cfg(procmacro2_backtrace)] { let backtrace = std::backtrace::Backtrace::force_capture(); panic!("compiler/fallback mismatch L{}\n\n{}", line, backtrace) } #[cfg(not(procmacro2_backtrace))] { panic!("compiler/fallback mismatch L{}", line) }} impl DeferredTokenStream { fn new(stream: proc_macro::TokenStream) -> Self { DeferredTokenStream { stream, extra: Vec::new(), } } fn is_empty(&self) -> bool { self.stream.is_empty() && self.extra.is_empty() } fn evaluate_now(&mut self) { // If-check provides a fast short circuit for the common case of `extra` // being empty, which saves a round trip over the proc macro bridge. // Improves macro expansion time in winrt by 6% in debug mode. if !self.extra.is_empty() { self.stream.extend(self.extra.drain(..)); } } fn into_token_stream(mut self) -> proc_macro::TokenStream { self.evaluate_now(); self.stream }} impl TokenStream { pub(crate) fn new() -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) } else { TokenStream::Fallback(fallback::TokenStream::new()) } } pub(crate) fn from_str_checked(src: &str) -> Result<Self, LexError> { if inside_proc_macro() { Ok(TokenStream::Compiler(DeferredTokenStream::new( proc_macro::TokenStream::from_str_checked(src)?, ))) } else { Ok(TokenStream::Fallback( fallback::TokenStream::from_str_checked(src)?, )) } } pub(crate) fn is_empty(&self) -> bool { match self { TokenStream::Compiler(tts) => tts.is_empty(), TokenStream::Fallback(tts) => tts.is_empty(), } } fn unwrap_nightly(self) -> proc_macro::TokenStream { match self { TokenStream::Compiler(s) => s.into_token_stream(), TokenStream::Fallback(_) => mismatch(line!()), } } fn unwrap_stable(self) -> fallback::TokenStream { match self { TokenStream::Compiler(_) => mismatch(line!()), TokenStream::Fallback(s) => s, } }} impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f), TokenStream::Fallback(tts) => Display::fmt(tts, f), } }} impl From<proc_macro::TokenStream> for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { TokenStream::Compiler(DeferredTokenStream::new(inner)) }} impl From<TokenStream> for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { match inner { TokenStream::Compiler(inner) => inner.into_token_stream(), TokenStream::Fallback(inner) => { proc_macro::TokenStream::from_str_unchecked(&inner.to_string()) } } }} impl From<fallback::TokenStream> for TokenStream { fn from(inner: fallback::TokenStream) -> Self { TokenStream::Fallback(inner) }} // Assumes inside_proc_macro().fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { match token { TokenTree::Group(tt) => proc_macro::TokenTree::Group(tt.inner.unwrap_nightly()), TokenTree::Punct(tt) => { let spacing = match tt.spacing() { Spacing::Joint => proc_macro::Spacing::Joint, Spacing::Alone => proc_macro::Spacing::Alone, }; let mut punct = proc_macro::Punct::new(tt.as_char(), spacing); punct.set_span(tt.span().inner.unwrap_nightly()); proc_macro::TokenTree::Punct(punct) } TokenTree::Ident(tt) => proc_macro::TokenTree::Ident(tt.inner.unwrap_nightly()), TokenTree::Literal(tt) => proc_macro::TokenTree::Literal(tt.inner.unwrap_nightly()), }} impl From<TokenTree> for TokenStream { fn from(token: TokenTree) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::from( into_compiler_token(token), ))) } else { TokenStream::Fallback(fallback::TokenStream::from(token)) } }} impl FromIterator<TokenTree> for TokenStream { fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new( trees.into_iter().map(into_compiler_token).collect(), )) } else { TokenStream::Fallback(trees.into_iter().collect()) } }} impl FromIterator<TokenStream> for TokenStream { fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { let mut streams = streams.into_iter(); match streams.next() { Some(TokenStream::Compiler(mut first)) => { first.evaluate_now(); first.stream.extend(streams.map(|s| match s { TokenStream::Compiler(s) => s.into_token_stream(), TokenStream::Fallback(_) => mismatch(line!()), })); TokenStream::Compiler(first) } Some(TokenStream::Fallback(mut first)) => { first.extend(streams.map(|s| match s { TokenStream::Fallback(s) => s, TokenStream::Compiler(_) => mismatch(line!()), })); TokenStream::Fallback(first) } None => TokenStream::new(), } }} impl Extend<TokenTree> for TokenStream { fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, stream: I) { match self { TokenStream::Compiler(tts) => { // Here is the reason for DeferredTokenStream. for token in stream { tts.extra.push(into_compiler_token(token)); } } TokenStream::Fallback(tts) => tts.extend(stream), } }} impl Extend<TokenStream> for TokenStream { fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { match self { TokenStream::Compiler(tts) => { tts.evaluate_now(); tts.stream .extend(streams.into_iter().map(TokenStream::unwrap_nightly)); } TokenStream::Fallback(tts) => { tts.extend(streams.into_iter().map(TokenStream::unwrap_stable)); } } }} impl Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f), TokenStream::Fallback(tts) => Debug::fmt(tts, f), } }} impl LexError { pub(crate) fn span(&self) -> Span { match self { LexError::Compiler(_) | LexError::CompilerPanic => Span::call_site(), LexError::Fallback(e) => Span::Fallback(e.span()), } }} impl From<proc_macro::LexError> for LexError { fn from(e: proc_macro::LexError) -> Self { LexError::Compiler(e) }} impl From<fallback::LexError> for LexError { fn from(e: fallback::LexError) -> Self { LexError::Fallback(e) }} impl Debug for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { LexError::Compiler(e) => Debug::fmt(e, f), LexError::Fallback(e) => Debug::fmt(e, f), LexError::CompilerPanic => { let fallback = fallback::LexError::call_site(); Debug::fmt(&fallback, f) } } }} impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { LexError::Compiler(e) => Display::fmt(e, f), LexError::Fallback(e) => Display::fmt(e, f), LexError::CompilerPanic => { let fallback = fallback::LexError::call_site(); Display::fmt(&fallback, f) } } }} #[derive(Clone)]pub(crate) enum TokenTreeIter { Compiler(proc_macro::token_stream::IntoIter), Fallback(fallback::TokenTreeIter),} impl IntoIterator for TokenStream { type Item = TokenTree; type IntoIter = TokenTreeIter; fn into_iter(self) -> TokenTreeIter { match self { TokenStream::Compiler(tts) => { TokenTreeIter::Compiler(tts.into_token_stream().into_iter()) } TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()), } }} impl Iterator for TokenTreeIter { type Item = TokenTree; fn next(&mut self) -> Option<TokenTree> { let token = match self { TokenTreeIter::Compiler(iter) => iter.next()?, TokenTreeIter::Fallback(iter) => return iter.next(), }; Some(match token { proc_macro::TokenTree::Group(tt) => { TokenTree::Group(crate::Group::_new(Group::Compiler(tt))) } proc_macro::TokenTree::Punct(tt) => { let spacing = match tt.spacing() { proc_macro::Spacing::Joint => Spacing::Joint, proc_macro::Spacing::Alone => Spacing::Alone, }; let mut o = Punct::new(tt.as_char(), spacing); o.set_span(crate::Span::_new(Span::Compiler(tt.span()))); TokenTree::Punct(o) } proc_macro::TokenTree::Ident(s) => { TokenTree::Ident(crate::Ident::_new(Ident::Compiler(s))) } proc_macro::TokenTree::Literal(l) => { TokenTree::Literal(crate::Literal::_new(Literal::Compiler(l))) } }) } fn size_hint(&self) -> (usize, Option<usize>) { match self { TokenTreeIter::Compiler(tts) => tts.size_hint(), TokenTreeIter::Fallback(tts) => tts.size_hint(), } }} #[derive(Copy, Clone)]pub(crate) enum Span { Compiler(proc_macro::Span), Fallback(fallback::Span),} impl Span { pub(crate) fn call_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::call_site()) } else { Span::Fallback(fallback::Span::call_site()) } } pub(crate) fn mixed_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::mixed_site()) } else { Span::Fallback(fallback::Span::mixed_site()) } } #[cfg(super_unstable)] pub(crate) fn def_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::def_site()) } else { Span::Fallback(fallback::Span::def_site()) } } pub(crate) fn resolved_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub(crate) fn located_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub(crate) fn unwrap(self) -> proc_macro::Span { match self { Span::Compiler(s) => s, Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"), } } #[cfg(span_locations)] pub(crate) fn byte_range(&self) -> Range<usize> { match self { #[cfg(proc_macro_span)] Span::Compiler(s) => proc_macro_span::byte_range(s), #[cfg(not(proc_macro_span))] Span::Compiler(_) => 0..0, Span::Fallback(s) => s.byte_range(), } } #[cfg(span_locations)] pub(crate) fn start(&self) -> LineColumn { match self { #[cfg(proc_macro_span_location)] Span::Compiler(s) => LineColumn { line: proc_macro_span_location::line(s), column: proc_macro_span_location::column(s).saturating_sub(1), }, #[cfg(not(proc_macro_span_location))] Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.start(), } } #[cfg(span_locations)] pub(crate) fn end(&self) -> LineColumn { match self { #[cfg(proc_macro_span_location)] Span::Compiler(s) => { let end = proc_macro_span_location::end(s); LineColumn { line: proc_macro_span_location::line(&end), column: proc_macro_span_location::column(&end).saturating_sub(1), } } #[cfg(not(proc_macro_span_location))] Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.end(), } } #[cfg(span_locations)] pub(crate) fn file(&self) -> String { match self { #[cfg(proc_macro_span_file)] Span::Compiler(s) => proc_macro_span_file::file(s), #[cfg(not(proc_macro_span_file))] Span::Compiler(_) => "<token stream>".to_owned(), Span::Fallback(s) => s.file(), } } #[cfg(span_locations)] pub(crate) fn local_file(&self) -> Option<PathBuf> { match self { #[cfg(proc_macro_span_file)] Span::Compiler(s) => proc_macro_span_file::local_file(s), #[cfg(not(proc_macro_span_file))] Span::Compiler(_) => None, Span::Fallback(s) => s.local_file(), } } pub(crate) fn join(&self, other: Span) -> Option<Span> { let ret = match (self, other) { #[cfg(proc_macro_span)] (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(proc_macro_span::join(a, b)?), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), _ => return None, }; Some(ret) }Lines 1–500 of 986. Load more
// SPDX-License-Identifier: Apache-2.0 OR MIT use crate::detection::inside_proc_macro; use crate::fallback::{self, FromStr2 as _}; #[cfg(span_locations)] use crate::location::LineColumn; #[cfg(proc_macro_span)] use crate::probe::proc_macro_span; #[cfg(all(span_locations, proc_macro_span_file))] use crate::probe::proc_macro_span_file; #[cfg(all(span_locations, proc_macro_span_location))] use crate::probe::proc_macro_span_location; use crate::{Delimiter, Punct, Spacing, TokenTree}; use core::fmt::{self, Debug, Display}; #[cfg(span_locations)] use core::ops::Range; use core::ops::RangeBounds; use std::ffi::CStr; #[cfg(span_locations)] use std::path::PathBuf; #[derive(Clone)] pub(crate) enum TokenStream { Compiler(DeferredTokenStream), Fallback(fallback::TokenStream), } // Work around https://github.com/rust-lang/rust/issues/65080. // In `impl Extend<TokenTree> for TokenStream` which is used heavily by quote, // we hold on to the appended tokens and do proc_macro::TokenStream::extend as // late as possible to batch together consecutive uses of the Extend impl. #[derive(Clone)] pub(crate) struct DeferredTokenStream { stream: proc_macro::TokenStream, extra: Vec<proc_macro::TokenTree>, } pub(crate) enum LexError { Compiler(proc_macro::LexError), Fallback(fallback::LexError), // Rustc was supposed to return a LexError, but it panicked instead. // https://github.com/rust-lang/rust/issues/58736 CompilerPanic, } #[cold] fn mismatch(line: u32) -> ! { #[cfg(procmacro2_backtrace)] { let backtrace = std::backtrace::Backtrace::force_capture(); panic!("compiler/fallback mismatch L{}\n\n{}", line, backtrace) } #[cfg(not(procmacro2_backtrace))] { panic!("compiler/fallback mismatch L{}", line) } } impl DeferredTokenStream { fn new(stream: proc_macro::TokenStream) -> Self { DeferredTokenStream { stream, extra: Vec::new(), } } fn is_empty(&self) -> bool { self.stream.is_empty() && self.extra.is_empty() } fn evaluate_now(&mut self) { // If-check provides a fast short circuit for the common case of `extra` // being empty, which saves a round trip over the proc macro bridge. // Improves macro expansion time in winrt by 6% in debug mode. if !self.extra.is_empty() { self.stream.extend(self.extra.drain(..)); } } fn into_token_stream(mut self) -> proc_macro::TokenStream { self.evaluate_now(); self.stream } } impl TokenStream { pub(crate) fn new() -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::new())) } else { TokenStream::Fallback(fallback::TokenStream::new()) } } pub(crate) fn from_str_checked(src: &str) -> Result<Self, LexError> { if inside_proc_macro() { Ok(TokenStream::Compiler(DeferredTokenStream::new( proc_macro::TokenStream::from_str_checked(src)?, ))) } else { Ok(TokenStream::Fallback( fallback::TokenStream::from_str_checked(src)?, )) } } pub(crate) fn is_empty(&self) -> bool { match self { TokenStream::Compiler(tts) => tts.is_empty(), TokenStream::Fallback(tts) => tts.is_empty(), } } fn unwrap_nightly(self) -> proc_macro::TokenStream { match self { TokenStream::Compiler(s) => s.into_token_stream(), TokenStream::Fallback(_) => mismatch(line!()), } } fn unwrap_stable(self) -> fallback::TokenStream { match self { TokenStream::Compiler(_) => mismatch(line!()), TokenStream::Fallback(s) => s, } } } impl Display for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenStream::Compiler(tts) => Display::fmt(&tts.clone().into_token_stream(), f), TokenStream::Fallback(tts) => Display::fmt(tts, f), } } } impl From<proc_macro::TokenStream> for TokenStream { fn from(inner: proc_macro::TokenStream) -> Self { TokenStream::Compiler(DeferredTokenStream::new(inner)) } } impl From<TokenStream> for proc_macro::TokenStream { fn from(inner: TokenStream) -> Self { match inner { TokenStream::Compiler(inner) => inner.into_token_stream(), TokenStream::Fallback(inner) => { proc_macro::TokenStream::from_str_unchecked(&inner.to_string()) } } } } impl From<fallback::TokenStream> for TokenStream { fn from(inner: fallback::TokenStream) -> Self { TokenStream::Fallback(inner) } } // Assumes inside_proc_macro(). fn into_compiler_token(token: TokenTree) -> proc_macro::TokenTree { match token { TokenTree::Group(tt) => proc_macro::TokenTree::Group(tt.inner.unwrap_nightly()), TokenTree::Punct(tt) => { let spacing = match tt.spacing() { Spacing::Joint => proc_macro::Spacing::Joint, Spacing::Alone => proc_macro::Spacing::Alone, }; let mut punct = proc_macro::Punct::new(tt.as_char(), spacing); punct.set_span(tt.span().inner.unwrap_nightly()); proc_macro::TokenTree::Punct(punct) } TokenTree::Ident(tt) => proc_macro::TokenTree::Ident(tt.inner.unwrap_nightly()), TokenTree::Literal(tt) => proc_macro::TokenTree::Literal(tt.inner.unwrap_nightly()), } } impl From<TokenTree> for TokenStream { fn from(token: TokenTree) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new(proc_macro::TokenStream::from( into_compiler_token(token), ))) } else { TokenStream::Fallback(fallback::TokenStream::from(token)) } } } impl FromIterator<TokenTree> for TokenStream { fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self { if inside_proc_macro() { TokenStream::Compiler(DeferredTokenStream::new( trees.into_iter().map(into_compiler_token).collect(), )) } else { TokenStream::Fallback(trees.into_iter().collect()) } } } impl FromIterator<TokenStream> for TokenStream { fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { let mut streams = streams.into_iter(); match streams.next() { Some(TokenStream::Compiler(mut first)) => { first.evaluate_now(); first.stream.extend(streams.map(|s| match s { TokenStream::Compiler(s) => s.into_token_stream(), TokenStream::Fallback(_) => mismatch(line!()), })); TokenStream::Compiler(first) } Some(TokenStream::Fallback(mut first)) => { first.extend(streams.map(|s| match s { TokenStream::Fallback(s) => s, TokenStream::Compiler(_) => mismatch(line!()), })); TokenStream::Fallback(first) } None => TokenStream::new(), } } } impl Extend<TokenTree> for TokenStream { fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, stream: I) { match self { TokenStream::Compiler(tts) => { // Here is the reason for DeferredTokenStream. for token in stream { tts.extra.push(into_compiler_token(token)); } } TokenStream::Fallback(tts) => tts.extend(stream), } } } impl Extend<TokenStream> for TokenStream { fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { match self { TokenStream::Compiler(tts) => { tts.evaluate_now(); tts.stream .extend(streams.into_iter().map(TokenStream::unwrap_nightly)); } TokenStream::Fallback(tts) => { tts.extend(streams.into_iter().map(TokenStream::unwrap_stable)); } } } } impl Debug for TokenStream { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { TokenStream::Compiler(tts) => Debug::fmt(&tts.clone().into_token_stream(), f), TokenStream::Fallback(tts) => Debug::fmt(tts, f), } } } impl LexError { pub(crate) fn span(&self) -> Span { match self { LexError::Compiler(_) | LexError::CompilerPanic => Span::call_site(), LexError::Fallback(e) => Span::Fallback(e.span()), } } } impl From<proc_macro::LexError> for LexError { fn from(e: proc_macro::LexError) -> Self { LexError::Compiler(e) } } impl From<fallback::LexError> for LexError { fn from(e: fallback::LexError) -> Self { LexError::Fallback(e) } } impl Debug for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { LexError::Compiler(e) => Debug::fmt(e, f), LexError::Fallback(e) => Debug::fmt(e, f), LexError::CompilerPanic => { let fallback = fallback::LexError::call_site(); Debug::fmt(&fallback, f) } } } } impl Display for LexError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { LexError::Compiler(e) => Display::fmt(e, f), LexError::Fallback(e) => Display::fmt(e, f), LexError::CompilerPanic => { let fallback = fallback::LexError::call_site(); Display::fmt(&fallback, f) } } } } #[derive(Clone)] pub(crate) enum TokenTreeIter { Compiler(proc_macro::token_stream::IntoIter), Fallback(fallback::TokenTreeIter), } impl IntoIterator for TokenStream { type Item = TokenTree; type IntoIter = TokenTreeIter; fn into_iter(self) -> TokenTreeIter { match self { TokenStream::Compiler(tts) => { TokenTreeIter::Compiler(tts.into_token_stream().into_iter()) } TokenStream::Fallback(tts) => TokenTreeIter::Fallback(tts.into_iter()), } } } impl Iterator for TokenTreeIter { type Item = TokenTree; fn next(&mut self) -> Option<TokenTree> { let token = match self { TokenTreeIter::Compiler(iter) => iter.next()?, TokenTreeIter::Fallback(iter) => return iter.next(), }; Some(match token { proc_macro::TokenTree::Group(tt) => { TokenTree::Group(crate::Group::_new(Group::Compiler(tt))) } proc_macro::TokenTree::Punct(tt) => { let spacing = match tt.spacing() { proc_macro::Spacing::Joint => Spacing::Joint, proc_macro::Spacing::Alone => Spacing::Alone, }; let mut o = Punct::new(tt.as_char(), spacing); o.set_span(crate::Span::_new(Span::Compiler(tt.span()))); TokenTree::Punct(o) } proc_macro::TokenTree::Ident(s) => { TokenTree::Ident(crate::Ident::_new(Ident::Compiler(s))) } proc_macro::TokenTree::Literal(l) => { TokenTree::Literal(crate::Literal::_new(Literal::Compiler(l))) } }) } fn size_hint(&self) -> (usize, Option<usize>) { match self { TokenTreeIter::Compiler(tts) => tts.size_hint(), TokenTreeIter::Fallback(tts) => tts.size_hint(), } } } #[derive(Copy, Clone)] pub(crate) enum Span { Compiler(proc_macro::Span), Fallback(fallback::Span), } impl Span { pub(crate) fn call_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::call_site()) } else { Span::Fallback(fallback::Span::call_site()) } } pub(crate) fn mixed_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::mixed_site()) } else { Span::Fallback(fallback::Span::mixed_site()) } } #[cfg(super_unstable)] pub(crate) fn def_site() -> Self { if inside_proc_macro() { Span::Compiler(proc_macro::Span::def_site()) } else { Span::Fallback(fallback::Span::def_site()) } } pub(crate) fn resolved_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.resolved_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.resolved_at(b)), (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub(crate) fn located_at(&self, other: Span) -> Span { match (self, other) { (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.located_at(b)), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.located_at(b)), (Span::Compiler(_), Span::Fallback(_)) => mismatch(line!()), (Span::Fallback(_), Span::Compiler(_)) => mismatch(line!()), } } pub(crate) fn unwrap(self) -> proc_macro::Span { match self { Span::Compiler(s) => s, Span::Fallback(_) => panic!("proc_macro::Span is only available in procedural macros"), } } #[cfg(span_locations)] pub(crate) fn byte_range(&self) -> Range<usize> { match self { #[cfg(proc_macro_span)] Span::Compiler(s) => proc_macro_span::byte_range(s), #[cfg(not(proc_macro_span))] Span::Compiler(_) => 0..0, Span::Fallback(s) => s.byte_range(), } } #[cfg(span_locations)] pub(crate) fn start(&self) -> LineColumn { match self { #[cfg(proc_macro_span_location)] Span::Compiler(s) => LineColumn { line: proc_macro_span_location::line(s), column: proc_macro_span_location::column(s).saturating_sub(1), }, #[cfg(not(proc_macro_span_location))] Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.start(), } } #[cfg(span_locations)] pub(crate) fn end(&self) -> LineColumn { match self { #[cfg(proc_macro_span_location)] Span::Compiler(s) => { let end = proc_macro_span_location::end(s); LineColumn { line: proc_macro_span_location::line(&end), column: proc_macro_span_location::column(&end).saturating_sub(1), } } #[cfg(not(proc_macro_span_location))] Span::Compiler(_) => LineColumn { line: 0, column: 0 }, Span::Fallback(s) => s.end(), } } #[cfg(span_locations)] pub(crate) fn file(&self) -> String { match self { #[cfg(proc_macro_span_file)] Span::Compiler(s) => proc_macro_span_file::file(s), #[cfg(not(proc_macro_span_file))] Span::Compiler(_) => "<token stream>".to_owned(), Span::Fallback(s) => s.file(), } } #[cfg(span_locations)] pub(crate) fn local_file(&self) -> Option<PathBuf> { match self { #[cfg(proc_macro_span_file)] Span::Compiler(s) => proc_macro_span_file::local_file(s), #[cfg(not(proc_macro_span_file))] Span::Compiler(_) => None, Span::Fallback(s) => s.local_file(), } } pub(crate) fn join(&self, other: Span) -> Option<Span> { let ret = match (self, other) { #[cfg(proc_macro_span)] (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(proc_macro_span::join(a, b)?), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), _ => return None, }; Some(ret) }