Skip to content

Commit

Permalink
Alternative approach with private types
Browse files Browse the repository at this point in the history
  • Loading branch information
dtolnay committed Mar 13, 2023
1 parent 3eb1954 commit 76b38b2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 30 deletions.
10 changes: 5 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -619,28 +619,28 @@ macro_rules! quote_spanned {
#[macro_export]
macro_rules! quote_spanned {
($span:expr=>) => {{
let _ = $crate::__private::GetSpan($span).__into_span();
let _ = $crate::__private::get_span($span).__into_span();
$crate::__private::TokenStream::new()
}};

// Special case rule for a single tt, for performance.
($span:expr=> $tt:tt) => {{
let mut _s = $crate::__private::TokenStream::new();
let _span = $crate::__private::GetSpan($span).__into_span();
let _span = $crate::__private::get_span($span).__into_span();
$crate::quote_token_spanned!{$tt _s _span}
_s
}};

// Special case rules for two tts, for performance.
($span:expr=> # $var:ident) => {{
let mut _s = $crate::__private::TokenStream::new();
let _ = $crate::__private::GetSpan($span).__into_span();
let _ = $crate::__private::get_span($span).__into_span();
$crate::ToTokens::to_tokens(&$var, &mut _s);
_s
}};
($span:expr=> $tt1:tt $tt2:tt) => {{
let mut _s = $crate::__private::TokenStream::new();
let _span = $crate::__private::GetSpan($span).__into_span();
let _span = $crate::__private::get_span($span).__into_span();
$crate::quote_token_spanned!{$tt1 _s _span}
$crate::quote_token_spanned!{$tt2 _s _span}
_s
Expand All @@ -649,7 +649,7 @@ macro_rules! quote_spanned {
// Rule for any other number of tokens.
($span:expr=> $($tt:tt)*) => {{
let mut _s = $crate::__private::TokenStream::new();
let _span = $crate::__private::GetSpan($span).__into_span();
let _span = $crate::__private::get_span($span).__into_span();
$crate::quote_each_token_spanned!{_s _span $($tt)*}
_s
}};
Expand Down
53 changes: 30 additions & 23 deletions src/runtime.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use self::get_span::{GetSpanInner, GetSpan};
use crate::{IdentFragment, ToTokens, TokenStreamExt};
use core::fmt;
use core::iter;
use core::ops::{BitOr, Deref};
use proc_macro2::extra::DelimSpan;
use core::ops::BitOr;
use proc_macro2::{Group, Ident, Punct, Spacing, TokenTree};

pub use core::option::Option;
Expand Down Expand Up @@ -166,34 +166,41 @@ impl<T: ToTokens> ToTokens for RepInterp<T> {
}
}

#[repr(transparent)]
pub struct GetSpan<T>(pub T);

#[repr(transparent)]
pub struct WrapperDelimSpan {
span: DelimSpan,
#[inline]
pub fn get_span<T>(span: T) -> GetSpan<T> {
GetSpan(GetSpanInner(span))
}

impl GetSpan<Span> {
#[inline]
pub fn __into_span(self) -> Span {
self.0
mod get_span {
use core::ops::Deref;
use proc_macro2::extra::DelimSpan;
use proc_macro2::Span;

pub struct GetSpan<T>(pub(crate) GetSpanInner<T>);

pub struct GetSpanInner<T>(pub(crate) T);

impl GetSpan<Span> {
#[inline]
pub fn __into_span(self) -> Span {
self.0.0
}
}
}

impl WrapperDelimSpan {
#[inline]
pub fn __into_span(&self) -> Span {
self.span.join()
impl GetSpanInner<DelimSpan> {
#[inline]
pub fn __into_span(&self) -> Span {
self.0.join()
}
}
}

impl Deref for GetSpan<DelimSpan> {
type Target = WrapperDelimSpan;
impl Deref for GetSpan<DelimSpan> {
type Target = GetSpanInner<DelimSpan>;

#[inline]
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const GetSpan<DelimSpan> as *const WrapperDelimSpan) }
#[inline]
fn deref(&self) -> &Self::Target {
&self.0
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/wrong-type-span.stderr
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
error[E0599]: no method named `__into_span` found for struct `GetSpan<&str>` in the current scope
error[E0599]: no method named `__into_span` found for struct `__private::get_span::GetSpan<&str>` in the current scope
--> tests/ui/wrong-type-span.rs:6:5
|
6 | quote_spanned!(span=> #x);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `GetSpan<&str>`
|
= note: the method was found for
- `GetSpan<Span>`
- `__private::get_span::GetSpan<Span>`
= note: this error originates in the macro `quote_spanned` (in Nightly builds, run with -Z macro-backtrace for more info)

0 comments on commit 76b38b2

Please sign in to comment.