From 7a5d77da248199cc79019b3e264d2b8f5186f883 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 4 May 2024 07:38:30 +0200 Subject: Merging upstream version 1.0.81. Signed-off-by: Daniel Baumann --- src/fallback.rs | 207 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 145 insertions(+), 62 deletions(-) (limited to 'src/fallback.rs') diff --git a/src/fallback.rs b/src/fallback.rs index 7b40427..b42537b 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -11,9 +11,13 @@ use core::cell::RefCell; use core::cmp; use core::fmt::{self, Debug, Display, Write}; use core::mem::ManuallyDrop; +#[cfg(span_locations)] +use core::ops::Range; use core::ops::RangeBounds; use core::ptr; -use core::str::FromStr; +use core::str::{self, FromStr}; +use std::ffi::CStr; +#[cfg(procmacro2_semver_exempt)] use std::path::PathBuf; /// Force use of proc-macro2's fallback implementation of the API for now, even @@ -151,9 +155,9 @@ fn get_cursor(src: &str) -> Cursor { // Create a dummy file & add it to the source map #[cfg(not(fuzzing))] - SOURCE_MAP.with(|cm| { - let mut cm = cm.borrow_mut(); - let span = cm.add_file(src); + SOURCE_MAP.with(|sm| { + let mut sm = sm.borrow_mut(); + let span = sm.add_file(src); Cursor { rest: src, off: span.lo, @@ -295,11 +299,13 @@ impl IntoIterator for TokenStream { } } +#[cfg(procmacro2_semver_exempt)] #[derive(Clone, PartialEq, Eq)] pub(crate) struct SourceFile { path: PathBuf, } +#[cfg(procmacro2_semver_exempt)] impl SourceFile { /// Get the path to this source file as a string. pub fn path(&self) -> PathBuf { @@ -311,6 +317,7 @@ impl SourceFile { } } +#[cfg(procmacro2_semver_exempt)] impl Debug for SourceFile { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("SourceFile") @@ -334,6 +341,12 @@ thread_local! { }); } +#[cfg(span_locations)] +pub(crate) fn invalidate_current_thread_spans() { + #[cfg(not(fuzzing))] + SOURCE_MAP.with(|sm| sm.borrow_mut().files.truncate(1)); +} + #[cfg(all(span_locations, not(fuzzing)))] struct FileInfo { source_text: String, @@ -366,7 +379,7 @@ impl FileInfo { span.lo >= self.span.lo && span.hi <= self.span.hi } - fn source_text(&mut self, span: Span) -> String { + fn byte_range(&mut self, span: Span) -> Range { let lo_char = (span.lo - self.span.lo) as usize; // Look up offset of the largest already-computed char index that is @@ -395,11 +408,15 @@ impl FileInfo { let trunc_lo = &self.source_text[lo_byte..]; let char_len = (span.hi - span.lo) as usize; - let source_text = match trunc_lo.char_indices().nth(char_len) { - Some((offset, _ch)) => &trunc_lo[..offset], - None => trunc_lo, - }; - source_text.to_owned() + lo_byte..match trunc_lo.char_indices().nth(char_len) { + Some((offset, _ch)) => lo_byte + offset, + None => self.source_text.len(), + } + } + + fn source_text(&mut self, span: Span) -> String { + let byte_range = self.byte_range(span); + self.source_text[byte_range].to_owned() } } @@ -534,22 +551,37 @@ impl Span { }; #[cfg(not(fuzzing))] - SOURCE_MAP.with(|cm| { - let cm = cm.borrow(); - let path = cm.filepath(*self); + SOURCE_MAP.with(|sm| { + let sm = sm.borrow(); + let path = sm.filepath(*self); SourceFile { path } }) } + #[cfg(span_locations)] + pub fn byte_range(&self) -> Range { + #[cfg(fuzzing)] + return 0..0; + + #[cfg(not(fuzzing))] + { + if self.is_call_site() { + 0..0 + } else { + SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).byte_range(*self)) + } + } + } + #[cfg(span_locations)] pub fn start(&self) -> LineColumn { #[cfg(fuzzing)] return LineColumn { line: 0, column: 0 }; #[cfg(not(fuzzing))] - SOURCE_MAP.with(|cm| { - let cm = cm.borrow(); - let fi = cm.fileinfo(*self); + SOURCE_MAP.with(|sm| { + let sm = sm.borrow(); + let fi = sm.fileinfo(*self); fi.offset_line_column(self.lo as usize) }) } @@ -560,9 +592,9 @@ impl Span { return LineColumn { line: 0, column: 0 }; #[cfg(not(fuzzing))] - SOURCE_MAP.with(|cm| { - let cm = cm.borrow(); - let fi = cm.fileinfo(*self); + SOURCE_MAP.with(|sm| { + let sm = sm.borrow(); + let fi = sm.fileinfo(*self); fi.offset_line_column(self.hi as usize) }) } @@ -581,10 +613,10 @@ impl Span { }; #[cfg(not(fuzzing))] - SOURCE_MAP.with(|cm| { - let cm = cm.borrow(); + SOURCE_MAP.with(|sm| { + let sm = sm.borrow(); // If `other` is not within the same FileInfo as us, return None. - if !cm.fileinfo(*self).span_within(other) { + if !sm.fileinfo(*self).span_within(other) { return None; } Some(Span { @@ -609,7 +641,7 @@ impl Span { if self.is_call_site() { None } else { - Some(SOURCE_MAP.with(|cm| cm.borrow_mut().fileinfo_mut(*self).source_text(*self))) + Some(SOURCE_MAP.with(|sm| sm.borrow_mut().fileinfo_mut(*self).source_text(*self))) } } } @@ -895,7 +927,7 @@ impl Debug for Ident { #[derive(Clone)] pub(crate) struct Literal { - repr: String, + pub(crate) repr: String, span: Span, } @@ -976,71 +1008,98 @@ impl Literal { Literal::_new(s) } - pub fn string(t: &str) -> Literal { - let mut repr = String::with_capacity(t.len() + 2); + pub fn string(string: &str) -> Literal { + let mut repr = String::with_capacity(string.len() + 2); repr.push('"'); - let mut chars = t.chars(); - while let Some(ch) = chars.next() { - if ch == '\0' { - repr.push_str( - if chars - .as_str() - .starts_with(|next| '0' <= next && next <= '7') - { - // circumvent clippy::octal_escapes lint - "\\x00" - } else { - "\\0" - }, - ); - } else if ch == '\'' { - // escape_debug turns this into "\'" which is unnecessary. - repr.push(ch); - } else { - repr.extend(ch.escape_debug()); - } - } + escape_utf8(string, &mut repr); repr.push('"'); Literal::_new(repr) } - pub fn character(t: char) -> Literal { + pub fn character(ch: char) -> Literal { let mut repr = String::new(); repr.push('\''); - if t == '"' { + if ch == '"' { // escape_debug turns this into '\"' which is unnecessary. - repr.push(t); + repr.push(ch); } else { - repr.extend(t.escape_debug()); + repr.extend(ch.escape_debug()); + } + repr.push('\''); + Literal::_new(repr) + } + + pub fn byte_character(byte: u8) -> Literal { + let mut repr = "b'".to_string(); + #[allow(clippy::match_overlapping_arm)] + match byte { + b'\0' => repr.push_str(r"\0"), + b'\t' => repr.push_str(r"\t"), + b'\n' => repr.push_str(r"\n"), + b'\r' => repr.push_str(r"\r"), + b'\'' => repr.push_str(r"\'"), + b'\\' => repr.push_str(r"\\"), + b'\x20'..=b'\x7E' => repr.push(byte as char), + _ => { + let _ = write!(repr, r"\x{:02X}", byte); + } } repr.push('\''); Literal::_new(repr) } pub fn byte_string(bytes: &[u8]) -> Literal { - let mut escaped = "b\"".to_string(); + let mut repr = "b\"".to_string(); let mut bytes = bytes.iter(); while let Some(&b) = bytes.next() { #[allow(clippy::match_overlapping_arm)] match b { - b'\0' => escaped.push_str(match bytes.as_slice().first() { + b'\0' => repr.push_str(match bytes.as_slice().first() { // circumvent clippy::octal_escapes lint Some(b'0'..=b'7') => r"\x00", _ => r"\0", }), - b'\t' => escaped.push_str(r"\t"), - b'\n' => escaped.push_str(r"\n"), - b'\r' => escaped.push_str(r"\r"), - b'"' => escaped.push_str("\\\""), - b'\\' => escaped.push_str("\\\\"), - b'\x20'..=b'\x7E' => escaped.push(b as char), + b'\t' => repr.push_str(r"\t"), + b'\n' => repr.push_str(r"\n"), + b'\r' => repr.push_str(r"\r"), + b'"' => repr.push_str("\\\""), + b'\\' => repr.push_str(r"\\"), + b'\x20'..=b'\x7E' => repr.push(b as char), _ => { - let _ = write!(escaped, "\\x{:02X}", b); + let _ = write!(repr, r"\x{:02X}", b); + } + } + } + repr.push('"'); + Literal::_new(repr) + } + + pub fn c_string(string: &CStr) -> Literal { + let mut repr = "c\"".to_string(); + let mut bytes = string.to_bytes(); + while !bytes.is_empty() { + let (valid, invalid) = match str::from_utf8(bytes) { + Ok(all_valid) => { + bytes = b""; + (all_valid, bytes) + } + Err(utf8_error) => { + let (valid, rest) = bytes.split_at(utf8_error.valid_up_to()); + let valid = str::from_utf8(valid).unwrap(); + let invalid = utf8_error + .error_len() + .map_or(rest, |error_len| &rest[..error_len]); + bytes = &bytes[valid.len() + invalid.len()..]; + (valid, invalid) } + }; + escape_utf8(valid, &mut repr); + for &byte in invalid { + let _ = write!(repr, r"\x{:02X}", byte); } } - escaped.push('"'); - Literal::_new(escaped) + repr.push('"'); + Literal::_new(repr) } pub fn span(&self) -> Span { @@ -1141,3 +1200,27 @@ impl Debug for Literal { debug.finish() } } + +fn escape_utf8(string: &str, repr: &mut String) { + let mut chars = string.chars(); + while let Some(ch) = chars.next() { + if ch == '\0' { + repr.push_str( + if chars + .as_str() + .starts_with(|next| '0' <= next && next <= '7') + { + // circumvent clippy::octal_escapes lint + r"\x00" + } else { + r"\0" + }, + ); + } else if ch == '\'' { + // escape_debug turns this into "\'" which is unnecessary. + repr.push(ch); + } else { + repr.extend(ch.escape_debug()); + } + } +} -- cgit v1.2.3