aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fallback.rs20
-rw-r--r--src/lib.rs13
-rw-r--r--src/parse.rs4
-rw-r--r--src/wrapper.rs38
4 files changed, 67 insertions, 8 deletions
diff --git a/src/fallback.rs b/src/fallback.rs
index 50d10db..3d2feae 100644
--- a/src/fallback.rs
+++ b/src/fallback.rs
@@ -43,6 +43,12 @@ impl LexError {
pub(crate) fn span(&self) -> Span {
self.span
}
+
+ fn call_site() -> Self {
+ LexError {
+ span: Span::call_site(),
+ }
+ }
}
impl TokenStream {
@@ -887,6 +893,20 @@ impl Literal {
}
}
+impl FromStr for Literal {
+ type Err = LexError;
+
+ fn from_str(repr: &str) -> Result<Self, Self::Err> {
+ let cursor = get_cursor(repr);
+ if let Ok((_rest, literal)) = parse::literal(cursor) {
+ if literal.text.len() == repr.len() {
+ return Ok(literal);
+ }
+ }
+ Err(LexError::call_site())
+ }
+}
+
impl Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&self.text, f)
diff --git a/src/lib.rs b/src/lib.rs
index 9dec309..52d01f2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -78,7 +78,7 @@
//! a different thread.
// Proc-macro2 types in rustdoc of other crates get linked to here.
-#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.26")]
+#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.27")]
#![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))]
#![cfg_attr(super_unstable, feature(proc_macro_raw_ident, proc_macro_def_site))]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
@@ -1203,6 +1203,17 @@ impl Literal {
}
}
+impl FromStr for Literal {
+ type Err = LexError;
+
+ fn from_str(repr: &str) -> Result<Self, LexError> {
+ repr.parse().map(Literal::_new).map_err(|inner| LexError {
+ inner,
+ _marker: Marker,
+ })
+ }
+}
+
impl Debug for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Debug::fmt(&self.inner, f)
diff --git a/src/parse.rs b/src/parse.rs
index e5caed8..13a05a8 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -59,7 +59,7 @@ impl<'a> Cursor<'a> {
}
}
-struct Reject;
+pub(crate) struct Reject;
type PResult<'a, O> = Result<(Cursor<'a>, O), Reject>;
fn skip_whitespace(input: Cursor) -> Cursor {
@@ -310,7 +310,7 @@ fn ident_not_raw(input: Cursor) -> PResult<&str> {
Ok((input.advance(end), &input.rest[..end]))
}
-fn literal(input: Cursor) -> PResult<Literal> {
+pub(crate) fn literal(input: Cursor) -> PResult<Literal> {
let rest = literal_nocapture(input)?;
let end = input.len() - rest.len();
Ok((rest, Literal::_new(input.rest[..end].to_string())))
diff --git a/src/wrapper.rs b/src/wrapper.rs
index 24d86e8..2829dd7 100644
--- a/src/wrapper.rs
+++ b/src/wrapper.rs
@@ -29,6 +29,14 @@ pub(crate) enum LexError {
Fallback(fallback::LexError),
}
+impl LexError {
+ fn call_site() -> Self {
+ LexError::Fallback(fallback::LexError {
+ span: fallback::Span::call_site(),
+ })
+ }
+}
+
fn mismatch() -> ! {
panic!("stable/nightly mismatch")
}
@@ -108,11 +116,7 @@ impl FromStr for TokenStream {
// Work around https://github.com/rust-lang/rust/issues/58736.
fn proc_macro_parse(src: &str) -> Result<proc_macro::TokenStream, LexError> {
let result = panic::catch_unwind(|| src.parse().map_err(LexError::Compiler));
- result.unwrap_or_else(|_| {
- Err(LexError::Fallback(fallback::LexError {
- span: fallback::Span::call_site(),
- }))
- })
+ result.unwrap_or_else(|_| Err(LexError::call_site()))
}
impl Display for TokenStream {
@@ -912,6 +916,30 @@ impl From<fallback::Literal> for Literal {
}
}
+impl FromStr for Literal {
+ type Err = LexError;
+
+ fn from_str(repr: &str) -> Result<Self, Self::Err> {
+ if inside_proc_macro() {
+ // TODO: use libproc_macro's FromStr impl once it is available in
+ // rustc. https://github.com/rust-lang/rust/pull/84717
+ let tokens = proc_macro_parse(repr)?;
+ let mut iter = tokens.into_iter();
+ if let (Some(proc_macro::TokenTree::Literal(literal)), None) =
+ (iter.next(), iter.next())
+ {
+ if literal.to_string().len() == repr.len() {
+ return Ok(Literal::Compiler(literal));
+ }
+ }
+ Err(LexError::call_site())
+ } else {
+ let literal = fallback::Literal::from_str(repr)?;
+ Ok(Literal::Fallback(literal))
+ }
+ }
+}
+
impl Display for Literal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {