From 2ecccd0fc3d9eb147d14a73deebac2b83bd4ae4b Mon Sep 17 00:00:00 2001 From: Nika Layzell Date: Sun, 19 Jun 2022 19:32:07 -0400 Subject: [PATCH] Mark Ident::new_raw as no longer semver-exempt The previous Compiler behaviour appears to have been broken, in that it would return a non-raw string literal, so it was replaced with the fallback code from quote [1]. [1]: https://github.com/dtolnay/quote/blob/eeabf0d42ed68418741542ab5cfa8a9d339f8a79/src/runtime.rs#L409-L422 --- build.rs | 4 ++++ src/lib.rs | 4 ---- src/wrapper.rs | 23 +++++++++++++++-------- tests/test.rs | 1 - 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/build.rs b/build.rs index 1730ee68..38404967 100644 --- a/build.rs +++ b/build.rs @@ -84,6 +84,10 @@ fn main() { println!("cargo:rustc-cfg=no_hygiene"); } + if version.minor < 47 { + println!("cargo:rustc-cfg=no_ident_new_raw"); + } + if version.minor < 54 { println!("cargo:rustc-cfg=no_literal_from_str"); } diff --git a/src/lib.rs b/src/lib.rs index ba6b3f7d..16ec1335 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -953,10 +953,6 @@ impl Ident { } /// Same as `Ident::new`, but creates a raw identifier (`r#ident`). - /// - /// This method is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] - #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))] pub fn new_raw(string: &str, span: Span) -> Self { Ident::_new_raw(string, span) } diff --git a/src/wrapper.rs b/src/wrapper.rs index 2ba76ccd..b4c97fd9 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -694,16 +694,23 @@ impl Ident { pub fn new_raw(string: &str, span: Span) -> Self { match span { + #[cfg(not(no_ident_new_raw))] + Span::Compiler(s) => Ident::Compiler(proc_macro::Ident::new_raw(string, s)), + #[cfg(no_ident_new_raw)] Span::Compiler(s) => { - let p: proc_macro::TokenStream = string.parse().unwrap(); - let ident = match p.into_iter().next() { - Some(proc_macro::TokenTree::Ident(mut i)) => { - i.set_span(s); - i + let _ = proc_macro::Ident::new(string, s); + // At this point, the identifier is raw, and the unraw-ed version of it was + // successfully converted into an identifier. Try to produce a valid raw + // identifier by running the `TokenStream` parser, and unwrapping the first + // token as an `Ident`. + if let Ok(ts) = format!("r#{}", string).parse::() { + let mut iter = ts.into_iter(); + if let (Some(proc_macro::TokenTree::Ident(mut id)), None) = (iter.next(), iter.next()) { + id.set_span(s); + return Ident::Compiler(id); } - _ => panic!(), - }; - Ident::Compiler(ident) + } + panic!("not allowed as a raw identifier: {}", string) } Span::Fallback(s) => Ident::Fallback(fallback::Ident::new_raw(string, s)), } diff --git a/tests/test.rs b/tests/test.rs index a3e0d32c..794e7bf9 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -15,7 +15,6 @@ fn idents() { } #[test] -#[cfg(procmacro2_semver_exempt)] fn raw_idents() { assert_eq!( Ident::new_raw("String", Span::call_site()).to_string(),