diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 886f258f8fe98..8a0f150a5eac4 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -47,7 +47,7 @@ mod to_tokens; use core::convert::From; use core::ops::BitOr; use std::borrow::Cow; -use std::ffi::CStr; +use std::ffi::{CStr, CString}; use std::ops::{Range, RangeBounds}; use std::path::PathBuf; use std::str::FromStr; @@ -1697,7 +1697,7 @@ impl Literal { /// Returns the unescaped string value if the current literal is a c-string or a c-string /// literal. #[unstable(feature = "proc_macro_value", issue = "136652")] - pub fn cstr_value(&self) -> Result, ConversionErrorKind> { + pub fn cstr_value(&self) -> Result { self.0.symbol.with(|symbol| match self.0.kind { bridge::LitKind::CStr => { let mut error = None; @@ -1718,16 +1718,16 @@ impl Literal { Err(error) } else { buf.push(0); - Ok(buf) + // Safety: The `buf` content was already checked by the compiler when generating + // the literal. + unsafe { Ok(CString::from_vec_with_nul_unchecked(buf)) } } } bridge::LitKind::CStrRaw(_) => { // Raw strings have no escapes so we can convert the symbol // directly to a `Lrc` after appending the terminating NUL // char. - let mut buf = symbol.to_owned().into_bytes(); - buf.push(0); - Ok(buf) + Ok(CString::new(symbol.to_owned()).expect("invalid cstr literal")) } _ => Err(ConversionErrorKind::InvalidLiteralKind), }) diff --git a/tests/ui/proc-macro/auxiliary/api/literal.rs b/tests/ui/proc-macro/auxiliary/api/literal.rs index 890be9c290f1b..1e1571f6d919d 100644 --- a/tests/ui/proc-macro/auxiliary/api/literal.rs +++ b/tests/ui/proc-macro/auxiliary/api/literal.rs @@ -1,5 +1,10 @@ +// This code is part of a more global proc-macro testsuite. To run it: +// `./x.py test tests/ui/proc-macro/test.rs`. Also it's very frequent that even with modifications, +// it won't rerun, so don't forget to use `--force-rerun`. + // ignore-tidy-file-linelength +use std::ffi::CString; use proc_macro::{EscapeError, Literal, ConversionErrorKind}; pub fn test() { @@ -124,4 +129,10 @@ fn test_literal_value() { Literal::byte_character(b'B').byte_character_value(), Ok(b'B') ); + + assert_eq!(Literal::string("aA").str_value(), Ok("aA".to_string())); + assert_eq!(Literal::string("\t").str_value(), Ok("\t".to_string())); + + assert_eq!(Literal::c_string(c"aA").cstr_value().unwrap(), c"aA"); + assert_eq!(Literal::c_string(c"\t").cstr_value().unwrap(), c"\t"); }