summaryrefslogtreecommitdiffstats
path: root/vendor/proc-macro2
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/proc-macro2')
-rw-r--r--vendor/proc-macro2/.cargo-checksum.json2
-rw-r--r--vendor/proc-macro2/Cargo.toml2
-rw-r--r--vendor/proc-macro2/build.rs39
-rw-r--r--vendor/proc-macro2/rust-toolchain.toml2
-rw-r--r--vendor/proc-macro2/src/convert.rs19
-rw-r--r--vendor/proc-macro2/src/fallback.rs216
-rw-r--r--vendor/proc-macro2/src/lib.rs36
-rw-r--r--vendor/proc-macro2/src/parse.rs276
-rw-r--r--vendor/proc-macro2/src/rcvec.rs3
-rw-r--r--vendor/proc-macro2/src/wrapper.rs28
-rw-r--r--vendor/proc-macro2/tests/test.rs96
11 files changed, 480 insertions, 239 deletions
diff --git a/vendor/proc-macro2/.cargo-checksum.json b/vendor/proc-macro2/.cargo-checksum.json
index ccf5c1d78..b3e757eb9 100644
--- a/vendor/proc-macro2/.cargo-checksum.json
+++ b/vendor/proc-macro2/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"d3c6751efd93c8c4b4c37063e03cdf03d87a2e6fbc7928ce97df4cce487aab2a","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"32cbd395594db59ecc43d7866cfa2663f3687bb7df631781d60ae83200dae8a8","build.rs":"6d3f27a11cdddd6681fef0882a68abd7d256de79d87e90bf4632a373f140834e","src/detection.rs":"ed9a5f9a979ab01247d7a68eeb1afa3c13209334c5bfff0f9289cb07e5bb4e8b","src/extra.rs":"3447c89e4d83a94ebdf3599adb64050b92502da2a1f99a5cf36706e52d2c56dc","src/fallback.rs":"04bf8b1703f84c50997afdfbb506c1ecb53db54c92f808e13ee4a79d6cf4f023","src/lib.rs":"22c3a8849092a1e37ab5990ce79e8a7863c55eb5423d92abea1eea6807009c45","src/location.rs":"f55d2e61f1bb1af65e14ed04c9e91eb1ddbf8430e8c05f2048d1cd538d27368e","src/marker.rs":"344a8394f06a1d43355b514920e7e3c0c6dce507be767e3a590bbe3552edd110","src/parse.rs":"d98e38a2e97d18e1593add3cbb48a48406f1cff21592a1f37ffb6960664d919e","src/rcvec.rs":"49b6784c6ca5f32573cd8a83758b485d8acbfa126e5fb516ae439e429ef4c144","src/wrapper.rs":"be58a1d86bb422e6ff7668fce3244ee8ca39dc9128272cabb4a0f0c739e36794","tests/comments.rs":"31115b3a56c83d93eef2fb4c9566bf4543e302560732986161b98aef504785ed","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"bc86b7260e29dfc8cd3e01b0d3fb9e88f17442dc83235f264e8cacc5ab4fe23d","tests/test.rs":"cf3c944f1c4a09c326b1e639f70c173f0d93d916fb50c085542e44fad691eea7","tests/test_fmt.rs":"9357769945784354909259084ec8b34d2aa52081dd3967cac6dae3a5e3df3bc0","tests/test_size.rs":"acf05963c1e62052d769d237b50844a2c59b4182b491231b099a4f74e5456ab0"},"package":"ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"} \ No newline at end of file
+{"files":{"Cargo.toml":"2df39557439b577d897c0e14c6221c706e4f0bbd6f8a69034456540f89413a9b","LICENSE-APACHE":"62c7a1e35f56406896d7aa7ca52d0cc0d272ac022b5d2796e7d6905db8a3636a","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"32cbd395594db59ecc43d7866cfa2663f3687bb7df631781d60ae83200dae8a8","build.rs":"460c398e94aa491fa8c9242da0c6956fd7565f646a7b5fc6c971adbd79a206aa","rust-toolchain.toml":"6bbb61302978c736b2da03e4fb40e3beab908f85d533ab46fd541e637b5f3e0f","src/convert.rs":"0f8e0f472e49e0be79e65654065a752df1ac9ad55da43952ee7c86cb56940171","src/detection.rs":"ed9a5f9a979ab01247d7a68eeb1afa3c13209334c5bfff0f9289cb07e5bb4e8b","src/extra.rs":"3447c89e4d83a94ebdf3599adb64050b92502da2a1f99a5cf36706e52d2c56dc","src/fallback.rs":"a39b97b39fd3b9b1734767a948b7d2b5e3cf272cebae8c951d25f9124705fbfa","src/lib.rs":"8ff87fffbbd56761735ec0910a10f8f6c48017a1c78f349e02a0eb836d80e727","src/location.rs":"f55d2e61f1bb1af65e14ed04c9e91eb1ddbf8430e8c05f2048d1cd538d27368e","src/marker.rs":"344a8394f06a1d43355b514920e7e3c0c6dce507be767e3a590bbe3552edd110","src/parse.rs":"8f1f3c0bc130f60dcb7a7ed2ed3f46cec6472d2f2abd15e0a1647a8dc33c8e60","src/rcvec.rs":"6233164ae0afc5c74ddc9e27c7869ec523385a3e5bdb83c3662841e78af14982","src/wrapper.rs":"5b98af7cf798641d13fc2c5ff87cbcf3e5628710dbd90db6986fbfb649c7a429","tests/comments.rs":"31115b3a56c83d93eef2fb4c9566bf4543e302560732986161b98aef504785ed","tests/features.rs":"a86deb8644992a4eb64d9fd493eff16f9cf9c5cb6ade3a634ce0c990cf87d559","tests/marker.rs":"bc86b7260e29dfc8cd3e01b0d3fb9e88f17442dc83235f264e8cacc5ab4fe23d","tests/test.rs":"6c1d259c46c8f6d600df4890eee4f494aedeb2df9c979a177e3442a8c88889ac","tests/test_fmt.rs":"9357769945784354909259084ec8b34d2aa52081dd3967cac6dae3a5e3df3bc0","tests/test_size.rs":"acf05963c1e62052d769d237b50844a2c59b4182b491231b099a4f74e5456ab0"},"package":"78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da"} \ No newline at end of file
diff --git a/vendor/proc-macro2/Cargo.toml b/vendor/proc-macro2/Cargo.toml
index b6f170f20..71c095f66 100644
--- a/vendor/proc-macro2/Cargo.toml
+++ b/vendor/proc-macro2/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2018"
rust-version = "1.31"
name = "proc-macro2"
-version = "1.0.53"
+version = "1.0.64"
authors = [
"David Tolnay <dtolnay@gmail.com>",
"Alex Crichton <alex@alexcrichton.com>",
diff --git a/vendor/proc-macro2/build.rs b/vendor/proc-macro2/build.rs
index 59505a50c..0f4338dd3 100644
--- a/vendor/proc-macro2/build.rs
+++ b/vendor/proc-macro2/build.rs
@@ -1,11 +1,5 @@
// rustc-cfg emitted by the build script:
//
-// "use_proc_macro"
-// Link to extern crate proc_macro. Available on any compiler and any target
-// except wasm32. Requires "proc-macro" Cargo cfg to be enabled (default is
-// enabled). On wasm32 we never link to proc_macro even if "proc-macro" cfg
-// is enabled.
-//
// "wrap_proc_macro"
// Wrap types from libproc_macro rather than polyfilling the whole API.
// Enabled on rustc 1.29+ as long as procmacro2_semver_exempt is not set,
@@ -43,14 +37,15 @@
use std::env;
use std::process::{self, Command};
use std::str;
+use std::u32;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
- let version = match rustc_version() {
- Some(version) => version,
- None => return,
- };
+ let version = rustc_version().unwrap_or(RustcVersion {
+ minor: u32::MAX,
+ nightly: false,
+ });
if version.minor < 31 {
eprintln!("Minimum supported rustc version is 1.31");
@@ -72,6 +67,10 @@ fn main() {
println!("cargo:rustc-cfg=no_libprocmacro_unwind_safe");
}
+ if version.minor < 34 {
+ println!("cargo:rustc-cfg=no_try_from");
+ }
+
if version.minor < 39 {
println!("cargo:rustc-cfg=no_bind_by_move_pattern_guard");
}
@@ -104,21 +103,15 @@ fn main() {
println!("cargo:rustc-cfg=no_source_text");
}
- let target = env::var("TARGET").unwrap();
- if !enable_use_proc_macro(&target) {
+ if !cfg!(feature = "proc-macro") {
return;
}
- println!("cargo:rustc-cfg=use_proc_macro");
-
if version.nightly || !semver_exempt {
println!("cargo:rustc-cfg=wrap_proc_macro");
}
- if version.nightly
- && feature_allowed("proc_macro_span")
- && feature_allowed("proc_macro_span_shrink")
- {
+ if version.nightly && feature_allowed("proc_macro_span") {
println!("cargo:rustc-cfg=proc_macro_span");
}
@@ -127,16 +120,6 @@ fn main() {
}
}
-fn enable_use_proc_macro(target: &str) -> bool {
- // wasm targets don't have the `proc_macro` crate, disable this feature.
- if target.contains("wasm32") {
- return false;
- }
-
- // Otherwise, only enable it if our feature is actually enabled.
- cfg!(feature = "proc-macro")
-}
-
struct RustcVersion {
minor: u32,
nightly: bool,
diff --git a/vendor/proc-macro2/rust-toolchain.toml b/vendor/proc-macro2/rust-toolchain.toml
new file mode 100644
index 000000000..20fe888c3
--- /dev/null
+++ b/vendor/proc-macro2/rust-toolchain.toml
@@ -0,0 +1,2 @@
+[toolchain]
+components = ["rust-src"]
diff --git a/vendor/proc-macro2/src/convert.rs b/vendor/proc-macro2/src/convert.rs
new file mode 100644
index 000000000..afc5faf53
--- /dev/null
+++ b/vendor/proc-macro2/src/convert.rs
@@ -0,0 +1,19 @@
+pub(crate) fn usize_to_u32(u: usize) -> Option<u32> {
+ #[cfg(not(no_try_from))]
+ {
+ use core::convert::TryFrom;
+
+ u32::try_from(u).ok()
+ }
+
+ #[cfg(no_try_from)]
+ {
+ use core::mem;
+
+ if mem::size_of::<usize>() <= mem::size_of::<u32>() || u <= u32::max_value() as usize {
+ Some(u as u32)
+ } else {
+ None
+ }
+ }
+}
diff --git a/vendor/proc-macro2/src/fallback.rs b/vendor/proc-macro2/src/fallback.rs
index b0ed7b06f..1b8b12574 100644
--- a/vendor/proc-macro2/src/fallback.rs
+++ b/vendor/proc-macro2/src/fallback.rs
@@ -3,7 +3,7 @@ use crate::location::LineColumn;
use crate::parse::{self, Cursor};
use crate::rcvec::{RcVec, RcVecBuilder, RcVecIntoIter, RcVecMut};
use crate::{Delimiter, Spacing, TokenTree};
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
use core::cell::RefCell;
#[cfg(span_locations)]
use core::cmp;
@@ -13,8 +13,6 @@ use core::mem::ManuallyDrop;
use core::ops::RangeBounds;
use core::ptr;
use core::str::FromStr;
-#[cfg(procmacro2_semver_exempt)]
-use std::path::Path;
use std::path::PathBuf;
/// Force use of proc-macro2's fallback implementation of the API for now, even
@@ -162,11 +160,14 @@ impl TokenStreamBuilder {
#[cfg(span_locations)]
fn get_cursor(src: &str) -> Cursor {
+ #[cfg(fuzzing)]
+ return Cursor { rest: src, off: 1 };
+
// Create a dummy file & add it to the source map
+ #[cfg(not(fuzzing))]
SOURCE_MAP.with(|cm| {
let mut cm = cm.borrow_mut();
- let name = format!("<parsed string {}>", cm.files.len());
- let span = cm.add_file(&name, src);
+ let span = cm.add_file(src);
Cursor {
rest: src,
off: span.lo,
@@ -232,7 +233,7 @@ impl Debug for TokenStream {
}
}
-#[cfg(use_proc_macro)]
+#[cfg(feature = "proc-macro")]
impl From<proc_macro::TokenStream> for TokenStream {
fn from(inner: proc_macro::TokenStream) -> Self {
inner
@@ -242,7 +243,7 @@ impl From<proc_macro::TokenStream> for TokenStream {
}
}
-#[cfg(use_proc_macro)]
+#[cfg(feature = "proc-macro")]
impl From<TokenStream> for proc_macro::TokenStream {
fn from(inner: TokenStream) -> Self {
inner
@@ -334,14 +335,12 @@ impl Debug for SourceFile {
}
}
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
thread_local! {
static SOURCE_MAP: RefCell<SourceMap> = RefCell::new(SourceMap {
// NOTE: We start with a single dummy file which all call_site() and
// def_site() spans reference.
files: vec![FileInfo {
- #[cfg(procmacro2_semver_exempt)]
- name: "<unspecified>".to_owned(),
source_text: String::new(),
span: Span { lo: 0, hi: 0 },
lines: vec![0],
@@ -349,16 +348,14 @@ thread_local! {
});
}
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
struct FileInfo {
- #[cfg(procmacro2_semver_exempt)]
- name: String,
source_text: String,
span: Span,
lines: Vec<usize>,
}
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
impl FileInfo {
fn offset_line_column(&self, offset: usize) -> LineColumn {
assert!(self.span_within(Span {
@@ -391,7 +388,7 @@ impl FileInfo {
/// Computes the offsets of each line in the given source string
/// and the total number of characters
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
let mut lines = vec![0];
let mut total = 0;
@@ -406,12 +403,12 @@ fn lines_offsets(s: &str) -> (usize, Vec<usize>) {
(total, lines)
}
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
struct SourceMap {
files: Vec<FileInfo>,
}
-#[cfg(span_locations)]
+#[cfg(all(span_locations, not(fuzzing)))]
impl SourceMap {
fn next_start_pos(&self) -> u32 {
// Add 1 so there's always space between files.
@@ -421,7 +418,7 @@ impl SourceMap {
self.files.last().unwrap().span.hi + 1
}
- fn add_file(&mut self, name: &str, src: &str) -> Span {
+ fn add_file(&mut self, src: &str) -> Span {
let (len, lines) = lines_offsets(src);
let lo = self.next_start_pos();
// XXX(nika): Should we bother doing a checked cast or checked add here?
@@ -431,26 +428,35 @@ impl SourceMap {
};
self.files.push(FileInfo {
- #[cfg(procmacro2_semver_exempt)]
- name: name.to_owned(),
source_text: src.to_owned(),
span,
lines,
});
- #[cfg(not(procmacro2_semver_exempt))]
- let _ = name;
-
span
}
+ #[cfg(procmacro2_semver_exempt)]
+ fn filepath(&self, span: Span) -> PathBuf {
+ for (i, file) in self.files.iter().enumerate() {
+ if file.span_within(span) {
+ return PathBuf::from(if i == 0 {
+ "<unspecified>".to_owned()
+ } else {
+ format!("<parsed string {}>", i)
+ });
+ }
+ }
+ unreachable!("Invalid span with no related FileInfo!");
+ }
+
fn fileinfo(&self, span: Span) -> &FileInfo {
for file in &self.files {
if file.span_within(span) {
return file;
}
}
- panic!("Invalid span with no related FileInfo!");
+ unreachable!("Invalid span with no related FileInfo!");
}
}
@@ -496,17 +502,25 @@ impl Span {
#[cfg(procmacro2_semver_exempt)]
pub fn source_file(&self) -> SourceFile {
+ #[cfg(fuzzing)]
+ return SourceFile {
+ path: PathBuf::from("<unspecified>"),
+ };
+
+ #[cfg(not(fuzzing))]
SOURCE_MAP.with(|cm| {
let cm = cm.borrow();
- let fi = cm.fileinfo(*self);
- SourceFile {
- path: Path::new(&fi.name).to_owned(),
- }
+ let path = cm.filepath(*self);
+ SourceFile { path }
})
}
#[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);
@@ -516,6 +530,10 @@ impl Span {
#[cfg(span_locations)]
pub fn end(&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);
@@ -523,26 +541,6 @@ impl Span {
})
}
- #[cfg(procmacro2_semver_exempt)]
- pub fn before(&self) -> Span {
- Span {
- #[cfg(span_locations)]
- lo: self.lo,
- #[cfg(span_locations)]
- hi: self.lo,
- }
- }
-
- #[cfg(procmacro2_semver_exempt)]
- pub fn after(&self) -> Span {
- Span {
- #[cfg(span_locations)]
- lo: self.hi,
- #[cfg(span_locations)]
- hi: self.hi,
- }
- }
-
#[cfg(not(span_locations))]
pub fn join(&self, _other: Span) -> Option<Span> {
Some(Span {})
@@ -550,6 +548,13 @@ impl Span {
#[cfg(span_locations)]
pub fn join(&self, other: Span) -> Option<Span> {
+ #[cfg(fuzzing)]
+ return {
+ let _ = other;
+ None
+ };
+
+ #[cfg(not(fuzzing))]
SOURCE_MAP.with(|cm| {
let cm = cm.borrow();
// If `other` is not within the same FileInfo as us, return None.
@@ -570,10 +575,16 @@ impl Span {
#[cfg(span_locations)]
pub fn source_text(&self) -> Option<String> {
- if self.is_call_site() {
- None
- } else {
- Some(SOURCE_MAP.with(|cm| cm.borrow().fileinfo(*self).source_text(*self)))
+ #[cfg(fuzzing)]
+ return None;
+
+ #[cfg(not(fuzzing))]
+ {
+ if self.is_call_site() {
+ None
+ } else {
+ Some(SOURCE_MAP.with(|cm| cm.borrow().fileinfo(*self).source_text(*self)))
+ }
}
}
@@ -819,6 +830,7 @@ impl Display for Ident {
}
}
+#[allow(clippy::missing_fields_in_debug)]
impl Debug for Ident {
// Ident(proc_macro), Ident(r#union)
#[cfg(not(span_locations))]
@@ -927,12 +939,25 @@ impl Literal {
pub fn string(t: &str) -> Literal {
let mut repr = String::with_capacity(t.len() + 2);
repr.push('"');
- for c in t.chars() {
- if c == '\'' {
+ 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(c);
+ repr.push(ch);
} else {
- repr.extend(c.escape_debug());
+ repr.extend(ch.escape_debug());
}
}
repr.push('"');
@@ -954,16 +979,21 @@ impl Literal {
pub fn byte_string(bytes: &[u8]) -> Literal {
let mut escaped = "b\"".to_string();
- for b in bytes {
+ let mut bytes = bytes.iter();
+ while let Some(&b) = bytes.next() {
#[allow(clippy::match_overlapping_arm)]
- match *b {
- b'\0' => escaped.push_str(r"\0"),
+ match b {
+ b'\0' => escaped.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'\x20'..=b'\x7E' => escaped.push(b as char),
_ => {
let _ = write!(escaped, "\\x{:02X}", b);
}
@@ -981,28 +1011,76 @@ impl Literal {
self.span = span;
}
- pub fn subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span> {
- None
+ pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> {
+ #[cfg(not(span_locations))]
+ {
+ let _ = range;
+ None
+ }
+
+ #[cfg(span_locations)]
+ {
+ use crate::convert::usize_to_u32;
+ use core::ops::Bound;
+
+ let lo = match range.start_bound() {
+ Bound::Included(start) => {
+ let start = usize_to_u32(*start)?;
+ self.span.lo.checked_add(start)?
+ }
+ Bound::Excluded(start) => {
+ let start = usize_to_u32(*start)?;
+ self.span.lo.checked_add(start)?.checked_add(1)?
+ }
+ Bound::Unbounded => self.span.lo,
+ };
+ let hi = match range.end_bound() {
+ Bound::Included(end) => {
+ let end = usize_to_u32(*end)?;
+ self.span.lo.checked_add(end)?.checked_add(1)?
+ }
+ Bound::Excluded(end) => {
+ let end = usize_to_u32(*end)?;
+ self.span.lo.checked_add(end)?
+ }
+ Bound::Unbounded => self.span.hi,
+ };
+ if lo <= hi && hi <= self.span.hi {
+ Some(Span { lo, hi })
+ } else {
+ None
+ }
+ }
}
}
impl FromStr for Literal {
type Err = LexError;
- fn from_str(mut repr: &str) -> Result<Self, Self::Err> {
- let negative = repr.starts_with('-');
+ fn from_str(repr: &str) -> Result<Self, Self::Err> {
+ let mut cursor = get_cursor(repr);
+ #[cfg(span_locations)]
+ let lo = cursor.off;
+
+ let negative = cursor.starts_with_char('-');
if negative {
- repr = &repr[1..];
- if !repr.starts_with(|ch: char| ch.is_ascii_digit()) {
+ cursor = cursor.advance(1);
+ if !cursor.starts_with_fn(|ch| ch.is_ascii_digit()) {
return Err(LexError::call_site());
}
}
- let cursor = get_cursor(repr);
- if let Ok((_rest, mut literal)) = parse::literal(cursor) {
- if literal.repr.len() == repr.len() {
+
+ if let Ok((rest, mut literal)) = parse::literal(cursor) {
+ if rest.is_empty() {
if negative {
literal.repr.insert(0, '-');
}
+ literal.span = Span {
+ #[cfg(span_locations)]
+ lo,
+ #[cfg(span_locations)]
+ hi: rest.off,
+ };
return Ok(literal);
}
}
diff --git a/vendor/proc-macro2/src/lib.rs b/vendor/proc-macro2/src/lib.rs
index 138627a16..aa196be7c 100644
--- a/vendor/proc-macro2/src/lib.rs
+++ b/vendor/proc-macro2/src/lib.rs
@@ -86,11 +86,8 @@
//! 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.53")]
-#![cfg_attr(
- any(proc_macro_span, super_unstable),
- feature(proc_macro_span, proc_macro_span_shrink)
-)]
+#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.64")]
+#![cfg_attr(any(proc_macro_span, super_unstable), feature(proc_macro_span))]
#![cfg_attr(super_unstable, feature(proc_macro_def_site))]
#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(
@@ -102,6 +99,7 @@
clippy::manual_assert,
clippy::must_use_candidate,
clippy::needless_doctest_main,
+ clippy::new_without_default,
clippy::return_self_not_must_use,
clippy::shadow_unrelated,
clippy::trivially_copy_pass_by_ref,
@@ -119,7 +117,7 @@ compile_error! {"\
build script as well.
"}
-#[cfg(use_proc_macro)]
+#[cfg(feature = "proc-macro")]
extern crate proc_macro;
mod marker;
@@ -143,6 +141,8 @@ use crate::fallback as imp;
mod imp;
#[cfg(span_locations)]
+mod convert;
+#[cfg(span_locations)]
mod location;
use crate::extra::DelimSpan;
@@ -233,14 +233,16 @@ impl FromStr for TokenStream {
}
}
-#[cfg(use_proc_macro)]
+#[cfg(feature = "proc-macro")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
impl From<proc_macro::TokenStream> for TokenStream {
fn from(inner: proc_macro::TokenStream) -> Self {
TokenStream::_new(inner.into())
}
}
-#[cfg(use_proc_macro)]
+#[cfg(feature = "proc-macro")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "proc-macro")))]
impl From<TokenStream> for proc_macro::TokenStream {
fn from(inner: TokenStream) -> Self {
inner.inner.into()
@@ -489,24 +491,6 @@ impl Span {
self.inner.end()
}
- /// Creates an empty span pointing to directly before this span.
- ///
- /// This method is semver exempt and not exposed by default.
- #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))]
- #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))]
- pub fn before(&self) -> Span {
- Span::_new(self.inner.before())
- }
-
- /// Creates an empty span pointing to directly after this span.
- ///
- /// This method is semver exempt and not exposed by default.
- #[cfg(all(procmacro2_semver_exempt, any(not(wrap_proc_macro), super_unstable)))]
- #[cfg_attr(doc_cfg, doc(cfg(procmacro2_semver_exempt)))]
- pub fn after(&self) -> Span {
- Span::_new(self.inner.after())
- }
-
/// Create a new span encompassing `self` and `other`.
///
/// Returns `None` if `self` and `other` are from different files.
diff --git a/vendor/proc-macro2/src/parse.rs b/vendor/proc-macro2/src/parse.rs
index 82291da1b..21e324136 100644
--- a/vendor/proc-macro2/src/parse.rs
+++ b/vendor/proc-macro2/src/parse.rs
@@ -27,7 +27,18 @@ impl<'a> Cursor<'a> {
self.rest.starts_with(s)
}
- fn is_empty(&self) -> bool {
+ pub fn starts_with_char(&self, ch: char) -> bool {
+ self.rest.starts_with(ch)
+ }
+
+ pub fn starts_with_fn<Pattern>(&self, f: Pattern) -> bool
+ where
+ Pattern: FnMut(char) -> bool,
+ {
+ self.rest.starts_with(f)
+ }
+
+ pub fn is_empty(&self) -> bool {
self.rest.is_empty()
}
@@ -97,7 +108,7 @@ fn skip_whitespace(input: Cursor) -> Cursor {
s = s.advance(1);
continue;
}
- b if b <= 0x7f => {}
+ b if b.is_ascii() => {}
_ => {
let ch = s.chars().next().unwrap();
if is_whitespace(ch) {
@@ -262,9 +273,11 @@ fn leaf_token(input: Cursor) -> PResult<TokenTree> {
}
fn ident(input: Cursor) -> PResult<crate::Ident> {
- if ["r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#"]
- .iter()
- .any(|prefix| input.starts_with(prefix))
+ if [
+ "r\"", "r#\"", "r##", "b\"", "b\'", "br\"", "br#", "c\"", "cr\"", "cr#",
+ ]
+ .iter()
+ .any(|prefix| input.starts_with(prefix))
{
Err(Reject)
} else {
@@ -322,6 +335,8 @@ fn literal_nocapture(input: Cursor) -> Result<Cursor, Reject> {
Ok(ok)
} else if let Ok(ok) = byte_string(input) {
Ok(ok)
+ } else if let Ok(ok) = c_string(input) {
+ Ok(ok)
} else if let Ok(ok) = byte(input) {
Ok(ok)
} else if let Ok(ok) = character(input) {
@@ -352,8 +367,8 @@ fn string(input: Cursor) -> Result<Cursor, Reject> {
}
}
-fn cooked_string(input: Cursor) -> Result<Cursor, Reject> {
- let mut chars = input.char_indices().peekable();
+fn cooked_string(mut input: Cursor) -> Result<Cursor, Reject> {
+ let mut chars = input.char_indices();
while let Some((i, ch)) = chars.next() {
match ch {
@@ -367,31 +382,17 @@ fn cooked_string(input: Cursor) -> Result<Cursor, Reject> {
},
'\\' => match chars.next() {
Some((_, 'x')) => {
- if !backslash_x_char(&mut chars) {
- break;
- }
+ backslash_x_char(&mut chars)?;
}
Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
| Some((_, '\'')) | Some((_, '"')) | Some((_, '0')) => {}
Some((_, 'u')) => {
- if !backslash_u(&mut chars) {
- break;
- }
+ backslash_u(&mut chars)?;
}
- Some((_, ch @ '\n')) | Some((_, ch @ '\r')) => {
- let mut last = ch;
- loop {
- if last == '\r' && chars.next().map_or(true, |(_, ch)| ch != '\n') {
- return Err(Reject);
- }
- match chars.peek() {
- Some((_, ch)) if ch.is_whitespace() => {
- last = *ch;
- chars.next();
- }
- _ => break,
- }
- }
+ Some((newline, ch @ '\n')) | Some((newline, ch @ '\r')) => {
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, ch as u8)?;
+ chars = input.char_indices();
}
_ => break,
},
@@ -401,11 +402,30 @@ fn cooked_string(input: Cursor) -> Result<Cursor, Reject> {
Err(Reject)
}
+fn raw_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ _ => {}
+ }
+ }
+ Err(Reject)
+}
+
fn byte_string(input: Cursor) -> Result<Cursor, Reject> {
if let Ok(input) = input.parse("b\"") {
cooked_byte_string(input)
} else if let Ok(input) = input.parse("br") {
- raw_string(input)
+ raw_byte_string(input)
} else {
Err(Reject)
}
@@ -425,68 +445,127 @@ fn cooked_byte_string(mut input: Cursor) -> Result<Cursor, Reject> {
},
b'\\' => match bytes.next() {
Some((_, b'x')) => {
- if !backslash_x_byte(&mut bytes) {
- break;
- }
+ backslash_x_byte(&mut bytes)?;
}
Some((_, b'n')) | Some((_, b'r')) | Some((_, b't')) | Some((_, b'\\'))
| Some((_, b'0')) | Some((_, b'\'')) | Some((_, b'"')) => {}
Some((newline, b @ b'\n')) | Some((newline, b @ b'\r')) => {
- let mut last = b as char;
- let rest = input.advance(newline + 1);
- let mut chars = rest.char_indices();
- loop {
- if last == '\r' && chars.next().map_or(true, |(_, ch)| ch != '\n') {
- return Err(Reject);
- }
- match chars.next() {
- Some((_, ch)) if ch.is_whitespace() => last = ch,
- Some((offset, _)) => {
- input = rest.advance(offset);
- bytes = input.bytes().enumerate();
- break;
- }
- None => return Err(Reject),
- }
- }
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, b)?;
+ bytes = input.bytes().enumerate();
}
_ => break,
},
- b if b < 0x80 => {}
+ b if b.is_ascii() => {}
_ => break,
}
}
Err(Reject)
}
-fn raw_string(input: Cursor) -> Result<Cursor, Reject> {
- let mut chars = input.char_indices();
- let mut n = 0;
- for (i, ch) in &mut chars {
- match ch {
- '"' => {
- n = i;
- break;
+fn delimiter_of_raw_string(input: Cursor) -> PResult<&str> {
+ for (i, byte) in input.bytes().enumerate() {
+ match byte {
+ b'"' => {
+ if i > 255 {
+ // https://github.com/rust-lang/rust/pull/95251
+ return Err(Reject);
+ }
+ return Ok((input.advance(i + 1), &input.rest[..i]));
}
- '#' => {}
- _ => return Err(Reject),
+ b'#' => {}
+ _ => break,
}
}
- if n > 255 {
- // https://github.com/rust-lang/rust/pull/95251
- return Err(Reject);
+ Err(Reject)
+}
+
+fn raw_byte_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ other => {
+ if !other.is_ascii() {
+ break;
+ }
+ }
+ }
+ }
+ Err(Reject)
+}
+
+fn c_string(input: Cursor) -> Result<Cursor, Reject> {
+ if let Ok(input) = input.parse("c\"") {
+ cooked_c_string(input)
+ } else if let Ok(input) = input.parse("cr") {
+ raw_c_string(input)
+ } else {
+ Err(Reject)
+ }
+}
+
+fn raw_c_string(input: Cursor) -> Result<Cursor, Reject> {
+ let (input, delimiter) = delimiter_of_raw_string(input)?;
+ let mut bytes = input.bytes().enumerate();
+ while let Some((i, byte)) = bytes.next() {
+ match byte {
+ b'"' if input.rest[i + 1..].starts_with(delimiter) => {
+ let rest = input.advance(i + 1 + delimiter.len());
+ return Ok(literal_suffix(rest));
+ }
+ b'\r' => match bytes.next() {
+ Some((_, b'\n')) => {}
+ _ => break,
+ },
+ b'\0' => break,
+ _ => {}
+ }
}
+ Err(Reject)
+}
+
+fn cooked_c_string(mut input: Cursor) -> Result<Cursor, Reject> {
+ let mut chars = input.char_indices();
+
while let Some((i, ch)) = chars.next() {
match ch {
- '"' if input.rest[i + 1..].starts_with(&input.rest[..n]) => {
- let rest = input.advance(i + 1 + n);
- return Ok(literal_suffix(rest));
+ '"' => {
+ let input = input.advance(i + 1);
+ return Ok(literal_suffix(input));
}
'\r' => match chars.next() {
Some((_, '\n')) => {}
_ => break,
},
- _ => {}
+ '\\' => match chars.next() {
+ Some((_, 'x')) => {
+ backslash_x_nonzero(&mut chars)?;
+ }
+ Some((_, 'n')) | Some((_, 'r')) | Some((_, 't')) | Some((_, '\\'))
+ | Some((_, '\'')) | Some((_, '"')) => {}
+ Some((_, 'u')) => {
+ if backslash_u(&mut chars)? == '\0' {
+ break;
+ }
+ }
+ Some((newline, ch @ '\n')) | Some((newline, ch @ '\r')) => {
+ input = input.advance(newline + 1);
+ trailing_backslash(&mut input, ch as u8)?;
+ chars = input.char_indices();
+ }
+ _ => break,
+ },
+ '\0' => break,
+ _ch => {}
}
}
Err(Reject)
@@ -497,7 +576,7 @@ fn byte(input: Cursor) -> Result<Cursor, Reject> {
let mut bytes = input.bytes().enumerate();
let ok = match bytes.next().map(|(_, b)| b) {
Some(b'\\') => match bytes.next().map(|(_, b)| b) {
- Some(b'x') => backslash_x_byte(&mut bytes),
+ Some(b'x') => backslash_x_byte(&mut bytes).is_ok(),
Some(b'n') | Some(b'r') | Some(b't') | Some(b'\\') | Some(b'0') | Some(b'\'')
| Some(b'"') => true,
_ => false,
@@ -520,8 +599,8 @@ fn character(input: Cursor) -> Result<Cursor, Reject> {
let mut chars = input.char_indices();
let ok = match chars.next().map(|(_, ch)| ch) {
Some('\\') => match chars.next().map(|(_, ch)| ch) {
- Some('x') => backslash_x_char(&mut chars),
- Some('u') => backslash_u(&mut chars),
+ Some('x') => backslash_x_char(&mut chars).is_ok(),
+ Some('u') => backslash_u(&mut chars).is_ok(),
Some('n') | Some('r') | Some('t') | Some('\\') | Some('0') | Some('\'') | Some('"') => {
true
}
@@ -542,32 +621,45 @@ macro_rules! next_ch {
match $chars.next() {
Some((_, ch)) => match ch {
$pat $(| $rest)* => ch,
- _ => return false,
+ _ => return Err(Reject),
},
- None => return false,
+ None => return Err(Reject),
}
};
}
-fn backslash_x_char<I>(chars: &mut I) -> bool
+fn backslash_x_char<I>(chars: &mut I) -> Result<(), Reject>
where
I: Iterator<Item = (usize, char)>,
{
next_ch!(chars @ '0'..='7');
next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
- true
+ Ok(())
}
-fn backslash_x_byte<I>(chars: &mut I) -> bool
+fn backslash_x_byte<I>(chars: &mut I) -> Result<(), Reject>
where
I: Iterator<Item = (usize, u8)>,
{
next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
next_ch!(chars @ b'0'..=b'9' | b'a'..=b'f' | b'A'..=b'F');
- true
+ Ok(())
}
-fn backslash_u<I>(chars: &mut I) -> bool
+fn backslash_x_nonzero<I>(chars: &mut I) -> Result<(), Reject>
+where
+ I: Iterator<Item = (usize, char)>,
+{
+ let first = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+ let second = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F');
+ if first == '0' && second == '0' {
+ Err(Reject)
+ } else {
+ Ok(())
+ }
+}
+
+fn backslash_u<I>(chars: &mut I) -> Result<char, Reject>
where
I: Iterator<Item = (usize, char)>,
{
@@ -580,17 +672,37 @@ where
'a'..='f' => 10 + ch as u8 - b'a',
'A'..='F' => 10 + ch as u8 - b'A',
'_' if len > 0 => continue,
- '}' if len > 0 => return char::from_u32(value).is_some(),
- _ => return false,
+ '}' if len > 0 => return char::from_u32(value).ok_or(Reject),
+ _ => break,
};
if len == 6 {
- return false;
+ break;
}
value *= 0x10;
value += u32::from(digit);
len += 1;
}
- false
+ Err(Reject)
+}
+
+fn trailing_backslash(input: &mut Cursor, mut last: u8) -> Result<(), Reject> {
+ let mut whitespace = input.bytes().enumerate();
+ loop {
+ if last == b'\r' && whitespace.next().map_or(true, |(_, b)| b != b'\n') {
+ return Err(Reject);
+ }
+ match whitespace.next() {
+ Some((_, b @ b' ')) | Some((_, b @ b'\t')) | Some((_, b @ b'\n'))
+ | Some((_, b @ b'\r')) => {
+ last = b;
+ }
+ Some((offset, _)) => {
+ *input = input.advance(offset);
+ return Ok(());
+ }
+ None => return Err(Reject),
+ }
+ }
}
fn float(input: Cursor) -> Result<Cursor, Reject> {
@@ -756,7 +868,7 @@ fn digits(mut input: Cursor) -> Result<Cursor, Reject> {
fn punct(input: Cursor) -> PResult<Punct> {
let (rest, ch) = punct_char(input)?;
if ch == '\'' {
- if ident_any(rest)?.0.starts_with("'") {
+ if ident_any(rest)?.0.starts_with_char('\'') {
Err(Reject)
} else {
Ok((rest, Punct::new('\'', Spacing::Joint)))
@@ -848,7 +960,7 @@ fn doc_comment_contents(input: Cursor) -> PResult<(&str, bool)> {
Ok((input, (&s[3..s.len() - 2], true)))
} else if input.starts_with("///") {
let input = input.advance(3);
- if input.starts_with("/") {
+ if input.starts_with_char('/') {
return Err(Reject);
}
let (input, s) = take_until_newline_or_eof(input);
diff --git a/vendor/proc-macro2/src/rcvec.rs b/vendor/proc-macro2/src/rcvec.rs
index 86ca7d808..62298b42f 100644
--- a/vendor/proc-macro2/src/rcvec.rs
+++ b/vendor/proc-macro2/src/rcvec.rs
@@ -1,5 +1,6 @@
use core::mem;
use core::slice;
+use std::panic::RefUnwindSafe;
use std::rc::Rc;
use std::vec;
@@ -140,3 +141,5 @@ impl<T> Iterator for RcVecIntoIter<T> {
self.inner.size_hint()
}
}
+
+impl<T> RefUnwindSafe for RcVec<T> where T: RefUnwindSafe {}
diff --git a/vendor/proc-macro2/src/wrapper.rs b/vendor/proc-macro2/src/wrapper.rs
index 00f67cd62..c422e4f0c 100644
--- a/vendor/proc-macro2/src/wrapper.rs
+++ b/vendor/proc-macro2/src/wrapper.rs
@@ -470,12 +470,6 @@ impl Span {
#[cfg(span_locations)]
pub fn start(&self) -> LineColumn {
match self {
- #[cfg(proc_macro_span)]
- Span::Compiler(s) => {
- let proc_macro::LineColumn { line, column } = s.start();
- LineColumn { line, column }
- }
- #[cfg(not(proc_macro_span))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => s.start(),
}
@@ -484,33 +478,11 @@ impl Span {
#[cfg(span_locations)]
pub fn end(&self) -> LineColumn {
match self {
- #[cfg(proc_macro_span)]
- Span::Compiler(s) => {
- let proc_macro::LineColumn { line, column } = s.end();
- LineColumn { line, column }
- }
- #[cfg(not(proc_macro_span))]
Span::Compiler(_) => LineColumn { line: 0, column: 0 },
Span::Fallback(s) => s.end(),
}
}
- #[cfg(super_unstable)]
- pub fn before(&self) -> Span {
- match self {
- Span::Compiler(s) => Span::Compiler(s.before()),
- Span::Fallback(s) => Span::Fallback(s.before()),
- }
- }
-
- #[cfg(super_unstable)]
- pub fn after(&self) -> Span {
- match self {
- Span::Compiler(s) => Span::Compiler(s.after()),
- Span::Fallback(s) => Span::Fallback(s.after()),
- }
- }
-
pub fn join(&self, other: Span) -> Option<Span> {
let ret = match (self, other) {
#[cfg(proc_macro_span)]
diff --git a/vendor/proc-macro2/tests/test.rs b/vendor/proc-macro2/tests/test.rs
index e0af1512c..7792a0208 100644
--- a/vendor/proc-macro2/tests/test.rs
+++ b/vendor/proc-macro2/tests/test.rs
@@ -1,7 +1,8 @@
#![allow(
clippy::assertions_on_result_states,
clippy::items_after_statements,
- clippy::non_ascii_literal
+ clippy::non_ascii_literal,
+ clippy::octal_escapes
)]
use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
@@ -114,6 +115,13 @@ fn literal_string() {
assert_eq!(Literal::string("foo").to_string(), "\"foo\"");
assert_eq!(Literal::string("\"").to_string(), "\"\\\"\"");
assert_eq!(Literal::string("didn't").to_string(), "\"didn't\"");
+ assert_eq!(
+ Literal::string("a\00b\07c\08d\0e\0").to_string(),
+ "\"a\\x000b\\x007c\\08d\\0e\\0\"",
+ );
+
+ "\"\\\r\n x\"".parse::<TokenStream>().unwrap();
+ "\"\\\r\n \rx\"".parse::<TokenStream>().unwrap_err();
}
#[test]
@@ -147,6 +155,51 @@ fn literal_byte_string() {
Literal::byte_string(b"\0\t\n\r\"\\2\x10").to_string(),
"b\"\\0\\t\\n\\r\\\"\\\\2\\x10\"",
);
+ assert_eq!(
+ Literal::byte_string(b"a\00b\07c\08d\0e\0").to_string(),
+ "b\"a\\x000b\\x007c\\08d\\0e\\0\"",
+ );
+
+ "b\"\\\r\n x\"".parse::<TokenStream>().unwrap();
+ "b\"\\\r\n \rx\"".parse::<TokenStream>().unwrap_err();
+ "b\"\\\r\n \u{a0}x\"".parse::<TokenStream>().unwrap_err();
+ "br\"\u{a0}\"".parse::<TokenStream>().unwrap_err();
+}
+
+#[test]
+fn literal_c_string() {
+ let strings = r###"
+ c"hello\x80我叫\u{1F980}" // from the RFC
+ cr"\"
+ cr##"Hello "world"!"##
+ c"\t\n\r\"\\"
+ "###;
+
+ let mut tokens = strings.parse::<TokenStream>().unwrap().into_iter();
+
+ for expected in &[
+ r#"c"hello\x80我叫\u{1F980}""#,
+ r#"cr"\""#,
+ r###"cr##"Hello "world"!"##"###,
+ r#"c"\t\n\r\"\\""#,
+ ] {
+ match tokens.next().unwrap() {
+ TokenTree::Literal(literal) => {
+ assert_eq!(literal.to_string(), *expected);
+ }
+ unexpected => panic!("unexpected token: {:?}", unexpected),
+ }
+ }
+
+ if let Some(unexpected) = tokens.next() {
+ panic!("unexpected token: {:?}", unexpected);
+ }
+
+ for invalid in &[r#"c"\0""#, r#"c"\x00""#, r#"c"\u{0}""#, "c\"\0\""] {
+ if let Ok(unexpected) = invalid.parse::<TokenStream>() {
+ panic!("unexpected token: {:?}", unexpected);
+ }
+ }
}
#[test]
@@ -265,6 +318,30 @@ fn literal_parse() {
}
#[test]
+fn literal_span() {
+ let positive = "0.1".parse::<Literal>().unwrap();
+ let negative = "-0.1".parse::<Literal>().unwrap();
+ let subspan = positive.subspan(1..2);
+
+ #[cfg(not(span_locations))]
+ {
+ let _ = negative;
+ assert!(subspan.is_none());
+ }
+
+ #[cfg(span_locations)]
+ {
+ assert_eq!(positive.span().start().column, 0);
+ assert_eq!(positive.span().end().column, 3);
+ assert_eq!(negative.span().start().column, 0);
+ assert_eq!(negative.span().end().column, 4);
+ assert_eq!(subspan.unwrap().source_text().unwrap(), ".");
+ }
+
+ assert!(positive.subspan(1..4).is_none());
+}
+
+#[test]
fn roundtrip() {
fn roundtrip(p: &str) {
println!("parse: {}", p);
@@ -603,8 +680,8 @@ fn non_ascii_tokens() {
check_spans("/*** ábc */ x", &[(1, 12, 1, 13)]);
check_spans(r#""abc""#, &[(1, 0, 1, 5)]);
check_spans(r#""ábc""#, &[(1, 0, 1, 5)]);
- check_spans(r###"r#"abc"#"###, &[(1, 0, 1, 8)]);
- check_spans(r###"r#"ábc"#"###, &[(1, 0, 1, 8)]);
+ check_spans(r##"r#"abc"#"##, &[(1, 0, 1, 8)]);
+ check_spans(r##"r#"ábc"#"##, &[(1, 0, 1, 8)]);
check_spans("r#\"a\nc\"#", &[(1, 0, 2, 3)]);
check_spans("r#\"á\nc\"#", &[(1, 0, 2, 3)]);
check_spans("'a'", &[(1, 0, 1, 3)]);
@@ -624,7 +701,6 @@ fn non_ascii_tokens() {
check_spans("ábc// foo", &[(1, 0, 1, 3)]);
check_spans("ábć// foo", &[(1, 0, 1, 3)]);
check_spans("b\"a\\\n c\"", &[(1, 0, 2, 3)]);
- check_spans("b\"a\\\n\u{00a0}c\"", &[(1, 0, 2, 3)]);
}
#[cfg(span_locations)]
@@ -656,6 +732,18 @@ fn check_spans_internal(ts: TokenStream, lines: &mut &[(usize, usize, usize, usi
}
#[test]
+fn whitespace() {
+ // space, horizontal tab, vertical tab, form feed, carriage return, line
+ // feed, non-breaking space, left-to-right mark, right-to-left mark
+ let various_spaces = " \t\u{b}\u{c}\r\n\u{a0}\u{200e}\u{200f}";
+ let tokens = various_spaces.parse::<TokenStream>().unwrap();
+ assert_eq!(tokens.into_iter().count(), 0);
+
+ let lone_carriage_returns = " \r \r\r\n ";
+ lone_carriage_returns.parse::<TokenStream>().unwrap();
+}
+
+#[test]
fn byte_order_mark() {
let string = "\u{feff}foo";
let tokens = string.parse::<TokenStream>().unwrap();