diff options
author | Chih-Hung Hsieh <chh@google.com> | 2019-09-30 10:08:21 -0700 |
---|---|---|
committer | Chih-Hung Hsieh <chh@google.com> | 2019-09-30 10:58:41 -0700 |
commit | 1c4237a4269e453146942dcd7a2fbf57e2f0cbdd (patch) | |
tree | 531d0f7a9203b847f5c71df2f9e37c1ee18dd5dc | |
parent | 8379c689d8dff544f9104c55942ad8d6a39c19ac (diff) | |
parent | bdac3732544a3cfb73afe4548f550c369e906856 (diff) | |
download | proc-macro2-1c4237a4269e453146942dcd7a2fbf57e2f0cbdd.tar.gz |
Merge aosp/upstream-master to release 1.0.4
* Enable deny_warnings.
* Upgrade to edition 2018.
Test: mm in projects with Rust modules
Change-Id: I13d86d546afa2f5f39c69409d41dc9cd41b3a474
-rw-r--r-- | .travis.yml | 2 | ||||
-rw-r--r-- | Android.bp | 3 | ||||
-rw-r--r-- | Cargo.toml | 18 | ||||
-rw-r--r-- | README.md | 39 | ||||
-rw-r--r-- | build.rs | 52 | ||||
-rw-r--r-- | src/fallback.rs | 173 | ||||
-rw-r--r-- | src/lib.rs | 171 | ||||
-rw-r--r-- | src/strnom.rs | 6 | ||||
-rw-r--r-- | src/wrapper.rs | 98 | ||||
-rw-r--r-- | tests/features.rs | 8 | ||||
-rw-r--r-- | tests/marker.rs | 2 | ||||
-rw-r--r-- | tests/test.rs | 24 |
12 files changed, 297 insertions, 299 deletions
diff --git a/.travis.yml b/.travis.yml index 8f17d02..acddb57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ sudo: false matrix: include: - - rust: 1.15.0 - rust: 1.31.0 - rust: stable - rust: beta @@ -11,6 +10,7 @@ matrix: script: - cargo test - cargo test --no-default-features + - cargo test --no-default-features -- --ignored # run the ignored test to make sure the `proc-macro` feature is disabled - cargo test --features span-locations - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --no-default-features @@ -1,6 +1,5 @@ rust_library_rlib { name: "libproc_macro2", - deny_warnings: false, host_supported: true, crate_name: "proc_macro2", srcs: ["src/lib.rs"], @@ -14,5 +13,5 @@ rust_library_rlib { "default", "proc-macro", ], - edition: "2015", + edition: "2018", } @@ -1,29 +1,32 @@ [package] name = "proc-macro2" -version = "0.4.30" # remember to update html_root_url +version = "1.0.4" # remember to update html_root_url authors = ["Alex Crichton <alex@alexcrichton.com>"] -license = "MIT/Apache-2.0" +license = "MIT OR Apache-2.0" readme = "README.md" keywords = ["macros"] repository = "https://github.com/alexcrichton/proc-macro2" homepage = "https://github.com/alexcrichton/proc-macro2" documentation = "https://docs.rs/proc-macro2" -build = "build.rs" +edition = "2018" description = """ A stable implementation of the upcoming new `proc_macro` API. Comes with an option, off by default, to also reimplement itself in terms of the upstream unstable API. """ +[lib] +name = "proc_macro2" + [package.metadata.docs.rs] rustc-args = ["--cfg", "procmacro2_semver_exempt"] rustdoc-args = ["--cfg", "procmacro2_semver_exempt"] [dependencies] -unicode-xid = "0.1" +unicode-xid = "0.2" [dev-dependencies] -quote = "0.6" +quote = { version = "1.0", default_features = false } [features] proc-macro = [] @@ -46,11 +49,6 @@ travis-ci = { repository = "alexcrichton/proc-macro2" } # meaning impls would be missing when tested against types from the local # proc-macro2. # -# When publishing proc-macro2, Cargo will forbid publishing with a patch -# section. You need to delete this section and then publish with --allow-dirty. -# A PR https://github.com/rust-lang/cargo/pull/6535 proposes to make it no -# longer an error to publish with a patch section. -# # Travis builds that are in progress at the time that you publish may spuriously # fail. This is because they'll be building a local proc-macro2 which carries # the second-most-recent version number, pulling in quote which resolves to a @@ -5,7 +5,7 @@ [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://docs.rs/proc-macro2) A wrapper around the procedural macro API of the compiler's `proc_macro` crate. -This library serves three purposes: +This library serves two purposes: - **Bring proc-macro-like functionality to other contexts like build.rs and main.rs.** Types from `proc_macro` are entirely specific to procedural macros @@ -21,13 +21,6 @@ This library serves three purposes: unit test. In order for helper libraries or components of a macro to be testable in isolation, they must be implemented using `proc_macro2`. -- **Provide the latest and greatest APIs across all compiler versions.** - Procedural macros were first introduced to Rust in 1.15.0 with an extremely - minimal interface. Since then, many improvements have landed to make macros - more flexible and easier to write. This library tracks the procedural macro - API of the most recent stable compiler but employs a polyfill to provide that - API consistently across any compiler since 1.15.0. - [syn]: https://github.com/dtolnay/syn [quote]: https://github.com/dtolnay/quote @@ -35,7 +28,7 @@ This library serves three purposes: ```toml [dependencies] -proc-macro2 = "0.4" +proc-macro2 = "1.0" ``` The skeleton of a typical procedural macro typically looks like this: @@ -58,7 +51,7 @@ pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { If parsing with [Syn], you'll use [`parse_macro_input!`] instead to propagate parse errors correctly back to the compiler when parsing fails. -[`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html +[`parse_macro_input!`]: https://docs.rs/syn/1.0/syn/macro.parse_macro_input.html ## Unstable features @@ -67,10 +60,10 @@ API. Functionality in `proc_macro` that is not yet stable is not exposed by proc-macro2 by default. To opt into the additional APIs available in the most recent nightly compiler, -the `procmacro2_semver_exempt` config flag must be passed to rustc. As usual, we -will polyfill those nightly-only APIs all the way back to Rust 1.15.0. As these -are unstable APIs that track the nightly compiler, minor versions of proc-macro2 -may make breaking changes to them at any time. +the `procmacro2_semver_exempt` config flag must be passed to rustc. We will +polyfill those nightly-only APIs back to Rust 1.31.0. As these are unstable APIs +that track the nightly compiler, minor versions of proc-macro2 may make breaking +changes to them at any time. ``` RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build @@ -82,19 +75,19 @@ reminder that you are outside of the normal semver guarantees. Semver exempt methods are marked as such in the proc-macro2 documentation. -# License - -This project is licensed under either of +<br> - * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or - http://www.apache.org/licenses/LICENSE-2.0) - * MIT license ([LICENSE-MIT](LICENSE-MIT) or - http://opensource.org/licenses/MIT) +#### License -at your option. +<sup> +Licensed under either of <a href="LICENSE-APACHE">Apache License, Version +2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option. +</sup> -### Contribution +<br> +<sub> Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. +</sub> @@ -1,9 +1,5 @@ // rustc-cfg emitted by the build script: // -// "u128" -// Include u128 and i128 constructors for proc_macro2::Literal. Enabled on -// any compiler 1.26+. -// // "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 @@ -18,11 +14,6 @@ // procmacro2_semver_exempt surface area is implemented by using the // nightly-only proc_macro API. // -// "slow_extend" -// Fallback when `impl Extend for TokenStream` is not available. These impls -// were added one version later than the rest of the proc_macro token API. -// Enabled on rustc 1.29 only. -// // "proc_macro_span" // Enable non-dummy behavior of Span::start and Span::end methods which // requires an unstable compiler feature. Enabled when building with @@ -40,21 +31,20 @@ // location inside spans is a performance hit. use std::env; -use std::process::Command; +use std::process::{self, Command}; use std::str; fn main() { println!("cargo:rerun-if-changed=build.rs"); - let target = env::var("TARGET").unwrap(); - let version = match rustc_version() { Some(version) => version, None => return, }; - if version.minor >= 26 { - println!("cargo:rustc-cfg=u128"); + if version.minor < 31 { + eprintln!("Minimum supported rustc version is 1.31"); + process::exit(1); } let semver_exempt = cfg!(procmacro2_semver_exempt); @@ -67,21 +57,17 @@ fn main() { println!("cargo:rustc-cfg=span_locations"); } + let target = env::var("TARGET").unwrap(); if !enable_use_proc_macro(&target) { return; } println!("cargo:rustc-cfg=use_proc_macro"); - // Rust 1.29 stabilized the necessary APIs in the `proc_macro` crate - if version.nightly || version.minor >= 29 && !semver_exempt { + if version.nightly || !semver_exempt { println!("cargo:rustc-cfg=wrap_proc_macro"); } - if version.minor == 29 { - println!("cargo:rustc-cfg=slow_extend"); - } - if version.nightly && feature_allowed("proc_macro_span") { println!("cargo:rustc-cfg=proc_macro_span"); } @@ -107,30 +93,16 @@ struct RustcVersion { } fn rustc_version() -> Option<RustcVersion> { - macro_rules! otry { - ($e:expr) => { - match $e { - Some(e) => e, - None => return None, - } - }; - } - - let rustc = otry!(env::var_os("RUSTC")); - let output = otry!(Command::new(rustc).arg("--version").output().ok()); - let version = otry!(str::from_utf8(&output.stdout).ok()); - let nightly = version.contains("nightly"); + let rustc = env::var_os("RUSTC")?; + let output = Command::new(rustc).arg("--version").output().ok()?; + let version = str::from_utf8(&output.stdout).ok()?; + let nightly = version.contains("nightly") || version.contains("dev"); let mut pieces = version.split('.'); if pieces.next() != Some("rustc 1") { return None; } - let minor = otry!(pieces.next()); - let minor = otry!(minor.parse().ok()); - - Some(RustcVersion { - minor: minor, - nightly: nightly, - }) + let minor = pieces.next()?.parse().ok()?; + Some(RustcVersion { minor, nightly }) } fn feature_allowed(feature: &str) -> bool { diff --git a/src/fallback.rs b/src/fallback.rs index f40a874..fe582b3 100644 --- a/src/fallback.rs +++ b/src/fallback.rs @@ -1,20 +1,20 @@ #[cfg(span_locations)] use std::cell::RefCell; -#[cfg(procmacro2_semver_exempt)] +#[cfg(span_locations)] use std::cmp; use std::fmt; use std::iter; +use std::ops::RangeBounds; #[cfg(procmacro2_semver_exempt)] use std::path::Path; use std::path::PathBuf; use std::str::FromStr; use std::vec; -use strnom::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult}; +use crate::strnom::{block_comment, skip_whitespace, whitespace, word_break, Cursor, PResult}; +use crate::{Delimiter, Punct, Spacing, TokenTree}; use unicode_xid::UnicodeXID; -use {Delimiter, Punct, Spacing, TokenTree}; - #[derive(Clone)] pub struct TokenStream { inner: Vec<TokenTree>, @@ -118,8 +118,8 @@ impl fmt::Debug for TokenStream { } #[cfg(use_proc_macro)] -impl From<::proc_macro::TokenStream> for TokenStream { - fn from(inner: ::proc_macro::TokenStream) -> TokenStream { +impl From<proc_macro::TokenStream> for TokenStream { + fn from(inner: proc_macro::TokenStream) -> TokenStream { inner .to_string() .parse() @@ -128,8 +128,8 @@ impl From<::proc_macro::TokenStream> for TokenStream { } #[cfg(use_proc_macro)] -impl From<TokenStream> for ::proc_macro::TokenStream { - fn from(inner: TokenStream) -> ::proc_macro::TokenStream { +impl From<TokenStream> for proc_macro::TokenStream { + fn from(inner: TokenStream) -> proc_macro::TokenStream { inner .to_string() .parse() @@ -314,22 +314,19 @@ impl SourceMap { let lo = self.next_start_pos(); // XXX(nika): Shouild we bother doing a checked cast or checked add here? let span = Span { - lo: lo, + lo, hi: lo + (src.len() as u32), }; #[cfg(procmacro2_semver_exempt)] self.files.push(FileInfo { name: name.to_owned(), - span: span, - lines: lines, + span, + lines, }); #[cfg(not(procmacro2_semver_exempt))] - self.files.push(FileInfo { - span: span, - lines: lines, - }); + self.files.push(FileInfo { span, lines }); let _ = name; span @@ -411,7 +408,12 @@ impl Span { }) } - #[cfg(procmacro2_semver_exempt)] + #[cfg(not(span_locations))] + pub fn join(&self, _other: Span) -> Option<Span> { + Some(Span {}) + } + + #[cfg(span_locations)] pub fn join(&self, other: Span) -> Option<Span> { SOURCE_MAP.with(|cm| { let cm = cm.borrow(); @@ -453,8 +455,8 @@ pub struct Group { impl Group { pub fn new(delimiter: Delimiter, stream: TokenStream) -> Group { Group { - delimiter: delimiter, - stream: stream, + delimiter, + stream, span: Span::call_site(), } } @@ -471,12 +473,10 @@ impl Group { self.span } - #[cfg(procmacro2_semver_exempt)] pub fn span_open(&self) -> Span { self.span } - #[cfg(procmacro2_semver_exempt)] pub fn span_close(&self) -> Span { self.span } @@ -527,8 +527,8 @@ impl Ident { Ident { sym: string.to_owned(), - span: span, - raw: raw, + span, + raw, } } @@ -671,7 +671,7 @@ macro_rules! unsuffixed_numbers { impl Literal { fn _new(text: String) -> Literal { Literal { - text: text, + text, span: Span::call_site(), } } @@ -681,40 +681,32 @@ impl Literal { u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, + u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, + i128_suffixed => i128, isize_suffixed => isize, f32_suffixed => f32, f64_suffixed => f64, } - #[cfg(u128)] - suffixed_numbers! { - u128_suffixed => u128, - i128_suffixed => i128, - } - unsuffixed_numbers! { u8_unsuffixed => u8, u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, + u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, - isize_unsuffixed => isize, - } - - #[cfg(u128)] - unsuffixed_numbers! { - u128_unsuffixed => u128, i128_unsuffixed => i128, + isize_unsuffixed => isize, } pub fn f32_unsuffixed(f: f32) -> Literal { @@ -771,7 +763,7 @@ impl Literal { 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), _ => escaped.push_str(&format!("\\x{:02X}", b)), } } @@ -786,6 +778,10 @@ impl Literal { pub fn set_span(&mut self, span: Span) { self.span = span; } + + pub fn subspan<R: RangeBounds<usize>>(&self, _range: R) -> Option<Span> { + None + } } impl fmt::Display for Literal { @@ -831,21 +827,21 @@ fn token_stream(mut input: Cursor) -> PResult<TokenStream> { fn spanned<'a, T>( input: Cursor<'a>, f: fn(Cursor<'a>) -> PResult<'a, T>, -) -> PResult<'a, (T, ::Span)> { +) -> PResult<'a, (T, crate::Span)> { let (a, b) = f(skip_whitespace(input))?; - Ok((a, ((b, ::Span::_new_stable(Span::call_site()))))) + Ok((a, ((b, crate::Span::_new_stable(Span::call_site()))))) } #[cfg(span_locations)] fn spanned<'a, T>( input: Cursor<'a>, f: fn(Cursor<'a>) -> PResult<'a, T>, -) -> PResult<'a, (T, ::Span)> { +) -> PResult<'a, (T, crate::Span)> { let input = skip_whitespace(input); let lo = input.off; let (a, b) = f(input)?; let hi = a.off; - let span = ::Span::_new_stable(Span { lo: lo, hi: hi }); + let span = crate::Span::_new_stable(Span { lo, hi }); Ok((a, (b, span))) } @@ -856,9 +852,9 @@ fn token_tree(input: Cursor) -> PResult<TokenTree> { } named!(token_kind -> TokenTree, alt!( - map!(group, |g| TokenTree::Group(::Group::_new_stable(g))) + map!(group, |g| TokenTree::Group(crate::Group::_new_stable(g))) | - map!(literal, |l| TokenTree::Literal(::Literal::_new_stable(l))) // must be before symbol + map!(literal, |l| TokenTree::Literal(crate::Literal::_new_stable(l))) // must be before symbol | map!(op, TokenTree::Punct) | @@ -890,14 +886,27 @@ fn symbol_leading_ws(input: Cursor) -> PResult<TokenTree> { } fn symbol(input: Cursor) -> PResult<TokenTree> { - let mut chars = input.char_indices(); - let raw = input.starts_with("r#"); - if raw { - chars.next(); - chars.next(); + let rest = input.advance((raw as usize) << 1); + + let (rest, sym) = symbol_not_raw(rest)?; + + if !raw { + let ident = crate::Ident::new(sym, crate::Span::call_site()); + return Ok((rest, ident.into())); + } + + if sym == "_" { + return Err(LexError); } + let ident = crate::Ident::_new_raw(sym, crate::Span::call_site()); + Ok((rest, ident.into())) +} + +fn symbol_not_raw(input: Cursor) -> PResult<&str> { + let mut chars = input.char_indices(); + match chars.next() { Some((_, ch)) if is_ident_start(ch) => {} _ => return Err(LexError), @@ -911,17 +920,7 @@ fn symbol(input: Cursor) -> PResult<TokenTree> { } } - let a = &input.rest[..end]; - if a == "r#_" { - Err(LexError) - } else { - let ident = if raw { - ::Ident::_new_raw(&a[2..], ::Span::call_site()) - } else { - ::Ident::new(a, ::Span::call_site()) - }; - Ok((input.advance(end), ident.into())) - } + Ok((input.advance(end), &input.rest[..end])) } fn literal(input: Cursor) -> PResult<Literal> { @@ -961,10 +960,12 @@ named!(string -> (), alt!( ) => { |_| () } )); -named!(quoted_string -> (), delimited!( - punct!("\""), - cooked_string, - tag!("\"") +named!(quoted_string -> (), do_parse!( + punct!("\"") >> + cooked_string >> + tag!("\"") >> + option!(symbol_not_raw) >> + (()) )); fn cooked_string(input: Cursor) -> PResult<()> { @@ -1173,8 +1174,8 @@ fn backslash_x_char<I>(chars: &mut I) -> bool where I: Iterator<Item = (usize, char)>, { - next_ch!(chars @ '0'...'7'); - next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F'); + next_ch!(chars @ '0'..='7'); + next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); true } @@ -1182,8 +1183,8 @@ fn backslash_x_byte<I>(chars: &mut I) -> bool 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'); + 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 } @@ -1192,9 +1193,9 @@ where I: Iterator<Item = (usize, char)>, { next_ch!(chars @ '{'); - next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F'); + next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F'); loop { - let c = next_ch!(chars @ '0'...'9' | 'a'...'f' | 'A'...'F' | '_' | '}'); + let c = next_ch!(chars @ '0'..='9' | 'a'..='f' | 'A'..='F' | '_' | '}'); if c == '}' { return true; } @@ -1202,10 +1203,10 @@ where } fn float(input: Cursor) -> PResult<()> { - let (rest, ()) = float_digits(input)?; - for suffix in &["f32", "f64"] { - if rest.starts_with(suffix) { - return word_break(rest.advance(suffix.len())); + let (mut rest, ()) = float_digits(input)?; + if let Some(ch) = rest.chars().next() { + if is_ident_start(ch) { + rest = symbol_not_raw(rest)?.0; } } word_break(rest) @@ -1223,7 +1224,7 @@ fn float_digits(input: Cursor) -> PResult<()> { let mut has_exp = false; while let Some(&ch) = chars.peek() { match ch { - '0'...'9' | '_' => { + '0'..='9' | '_' => { chars.next(); len += 1; } @@ -1234,7 +1235,7 @@ fn float_digits(input: Cursor) -> PResult<()> { chars.next(); if chars .peek() - .map(|&ch| ch == '.' || UnicodeXID::is_xid_start(ch)) + .map(|&ch| ch == '.' || is_ident_start(ch)) .unwrap_or(false) { return Err(LexError); @@ -1268,7 +1269,7 @@ fn float_digits(input: Cursor) -> PResult<()> { chars.next(); len += 1; } - '0'...'9' => { + '0'..='9' => { chars.next(); len += 1; has_exp_value = true; @@ -1289,12 +1290,10 @@ fn float_digits(input: Cursor) -> PResult<()> { } fn int(input: Cursor) -> PResult<()> { - let (rest, ()) = digits(input)?; - for suffix in &[ - "isize", "i8", "i16", "i32", "i64", "i128", "usize", "u8", "u16", "u32", "u64", "u128", - ] { - if rest.starts_with(suffix) { - return word_break(rest.advance(suffix.len())); + let (mut rest, ()) = digits(input)?; + if let Some(ch) = rest.chars().next() { + if is_ident_start(ch) { + rest = symbol_not_raw(rest)?.0; } } word_break(rest) @@ -1318,9 +1317,9 @@ fn digits(mut input: Cursor) -> PResult<()> { let mut empty = true; for b in input.bytes() { let digit = match b { - b'0'...b'9' => (b - b'0') as u64, - b'a'...b'f' => 10 + (b - b'a') as u64, - b'A'...b'F' => 10 + (b - b'A') as u64, + b'0'..=b'9' => (b - b'0') as u64, + b'a'..=b'f' => 10 + (b - b'a') as u64, + b'A'..=b'F' => 10 + (b - b'A') as u64, b'_' => { if empty && base == 10 { return Err(LexError); @@ -1390,15 +1389,15 @@ fn doc_comment(input: Cursor) -> PResult<Vec<TokenTree>> { trees.push(Punct::new('!', Spacing::Alone).into()); } let mut stream = vec![ - TokenTree::Ident(::Ident::new("doc", span)), + TokenTree::Ident(crate::Ident::new("doc", span)), TokenTree::Punct(Punct::new('=', Spacing::Alone)), - TokenTree::Literal(::Literal::string(comment)), + TokenTree::Literal(crate::Literal::string(comment)), ]; for tt in stream.iter_mut() { tt.set_span(span); } let group = Group::new(Delimiter::Bracket, stream.into_iter().collect()); - trees.push(::Group::_new_stable(group).into()); + trees.push(crate::Group::_new_stable(group).into()); for tt in trees.iter_mut() { tt.set_span(span); } @@ -1,5 +1,5 @@ //! A wrapper around the procedural macro API of the compiler's [`proc_macro`] -//! crate. This library serves three purposes: +//! crate. This library serves two purposes: //! //! [`proc_macro`]: https://doc.rust-lang.org/proc_macro/ //! @@ -18,14 +18,6 @@ //! a macro to be testable in isolation, they must be implemented using //! `proc_macro2`. //! -//! - **Provide the latest and greatest APIs across all compiler versions.** -//! Procedural macros were first introduced to Rust in 1.15.0 with an -//! extremely minimal interface. Since then, many improvements have landed to -//! make macros more flexible and easier to write. This library tracks the -//! procedural macro API of the most recent stable compiler but employs a -//! polyfill to provide that API consistently across any compiler since -//! 1.15.0. -//! //! [syn]: https://github.com/dtolnay/syn //! [quote]: https://github.com/dtolnay/quote //! @@ -33,12 +25,13 @@ //! //! The skeleton of a typical procedural macro typically looks like this: //! -//! ```edition2018 +//! ``` //! extern crate proc_macro; //! //! # const IGNORE: &str = stringify! { //! #[proc_macro_derive(MyDerive)] //! # }; +//! # #[cfg(wrap_proc_macro)] //! pub fn my_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream { //! let input = proc_macro2::TokenStream::from(input); //! @@ -54,7 +47,7 @@ //! If parsing with [Syn], you'll use [`parse_macro_input!`] instead to //! propagate parse errors correctly back to the compiler when parsing fails. //! -//! [`parse_macro_input!`]: https://docs.rs/syn/0.15/syn/macro.parse_macro_input.html +//! [`parse_macro_input!`]: https://docs.rs/syn/1.0/syn/macro.parse_macro_input.html //! //! # Unstable features //! @@ -64,9 +57,9 @@ //! //! To opt into the additional APIs available in the most recent nightly //! compiler, the `procmacro2_semver_exempt` config flag must be passed to -//! rustc. As usual, we will polyfill those nightly-only APIs all the way back -//! to Rust 1.15.0. As these are unstable APIs that track the nightly compiler, -//! minor versions of proc-macro2 may make breaking changes to them at any time. +//! rustc. We will polyfill those nightly-only APIs back to Rust 1.31.0. As +//! these are unstable APIs that track the nightly compiler, minor versions of +//! proc-macro2 may make breaking changes to them at any time. //! //! ```sh //! RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build @@ -77,21 +70,27 @@ //! as a reminder that you are outside of the normal semver guarantees. //! //! Semver exempt methods are marked as such in the proc-macro2 documentation. +//! +//! # Thread-Safety +//! +//! Most types in this crate are `!Sync` because the underlying compiler +//! types make use of thread-local memory, meaning they cannot be accessed from +//! a different thread. // Proc-macro2 types in rustdoc of other crates get linked to here. -#![doc(html_root_url = "https://docs.rs/proc-macro2/0.4.30")] +#![doc(html_root_url = "https://docs.rs/proc-macro2/1.0.4")] #![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(use_proc_macro)] extern crate proc_macro; -extern crate unicode_xid; use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; use std::marker; +use std::ops::RangeBounds; #[cfg(procmacro2_semver_exempt)] use std::path::PathBuf; use std::rc::Rc; @@ -102,7 +101,7 @@ mod strnom; mod fallback; #[cfg(not(wrap_proc_macro))] -use fallback as imp; +use crate::fallback as imp; #[path = "wrapper.rs"] #[cfg(wrap_proc_macro)] mod imp; @@ -129,7 +128,7 @@ pub struct LexError { impl TokenStream { fn _new(inner: imp::TokenStream) -> TokenStream { TokenStream { - inner: inner, + inner, _marker: marker::PhantomData, } } @@ -146,11 +145,6 @@ impl TokenStream { TokenStream::_new(imp::TokenStream::new()) } - #[deprecated(since = "0.4.4", note = "please use TokenStream::new")] - pub fn empty() -> TokenStream { - TokenStream::new() - } - /// Checks if this `TokenStream` is empty. pub fn is_empty(&self) -> bool { self.inner.is_empty() @@ -199,6 +193,12 @@ impl From<TokenStream> for proc_macro::TokenStream { } } +impl From<TokenTree> for TokenStream { + fn from(token: TokenTree) -> Self { + TokenStream::_new(imp::TokenStream::from(token)) + } +} + impl Extend<TokenTree> for TokenStream { fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) { self.inner.extend(streams) @@ -261,7 +261,7 @@ pub struct SourceFile { impl SourceFile { fn _new(inner: imp::SourceFile) -> Self { SourceFile { - inner: inner, + inner, _marker: marker::PhantomData, } } @@ -321,7 +321,7 @@ pub struct Span { impl Span { fn _new(inner: imp::Span) -> Span { Span { - inner: inner, + inner, _marker: marker::PhantomData, } } @@ -404,10 +404,7 @@ impl Span { #[cfg(span_locations)] pub fn start(&self) -> LineColumn { let imp::LineColumn { line, column } = self.inner.start(); - LineColumn { - line: line, - column: column, - } + LineColumn { line, column } } /// Get the ending line/column in the source file for this span. @@ -416,23 +413,23 @@ impl Span { #[cfg(span_locations)] pub fn end(&self) -> LineColumn { let imp::LineColumn { line, column } = self.inner.end(); - LineColumn { - line: line, - column: column, - } + LineColumn { line, column } } /// Create a new span encompassing `self` and `other`. /// /// Returns `None` if `self` and `other` are from different files. /// - /// This method is semver exempt and not exposed by default. - #[cfg(procmacro2_semver_exempt)] + /// Warning: the underlying [`proc_macro::Span::join`] method is + /// nightly-only. When called from within a procedural macro not using a + /// nightly compiler, this method will always return `None`. + /// + /// [`proc_macro::Span::join`]: https://doc.rust-lang.org/proc_macro/struct.Span.html#method.join pub fn join(&self, other: Span) -> Option<Span> { self.inner.join(other.inner).map(Span::_new) } - /// Compares to spans to see if they're equal. + /// Compares two spans to see if they're equal. /// /// This method is semver exempt and not exposed by default. #[cfg(procmacro2_semver_exempt)] @@ -576,7 +573,7 @@ pub enum Delimiter { impl Group { fn _new(inner: imp::Group) -> Self { - Group { inner: inner } + Group { inner } } fn _new_stable(inner: fallback::Group) -> Self { @@ -626,7 +623,6 @@ impl Group { /// pub fn span_open(&self) -> Span { /// ^ /// ``` - #[cfg(procmacro2_semver_exempt)] pub fn span_open(&self) -> Span { Span::_new(self.inner.span_open()) } @@ -637,7 +633,6 @@ impl Group { /// pub fn span_close(&self) -> Span { /// ^ /// ``` - #[cfg(procmacro2_semver_exempt)] pub fn span_close(&self) -> Span { Span::_new(self.inner.span_close()) } @@ -685,7 +680,7 @@ pub struct Punct { pub enum Spacing { /// E.g. `+` is `Alone` in `+ =`, `+ident` or `+()`. Alone, - /// E.g. `+` is `Joint` in `+=` or `'#`. + /// E.g. `+` is `Joint` in `+=` or `'` is `Joint` in `'#`. /// /// Additionally, single quote `'` can join with identifiers to form /// lifetimes `'ident`. @@ -702,8 +697,8 @@ impl Punct { /// which can be further configured with the `set_span` method below. pub fn new(op: char, spacing: Spacing) -> Punct { Punct { - op: op, - spacing: spacing, + op, + spacing, span: Span::call_site(), } } @@ -765,7 +760,7 @@ impl fmt::Debug for Punct { /// Rust keywords. Use `input.call(Ident::parse_any)` when parsing to match the /// behaviour of `Ident::new`. /// -/// [`Parse`]: https://docs.rs/syn/0.15/syn/parse/trait.Parse.html +/// [`Parse`]: https://docs.rs/syn/1.0/syn/parse/trait.Parse.html /// /// # Examples /// @@ -773,7 +768,7 @@ impl fmt::Debug for Punct { /// A span must be provided explicitly which governs the name resolution /// behavior of the resulting identifier. /// -/// ```edition2018 +/// ``` /// use proc_macro2::{Ident, Span}; /// /// fn main() { @@ -785,7 +780,7 @@ impl fmt::Debug for Punct { /// /// An ident can be interpolated into a token stream using the `quote!` macro. /// -/// ```edition2018 +/// ``` /// use proc_macro2::{Ident, Span}; /// use quote::quote; /// @@ -804,7 +799,7 @@ impl fmt::Debug for Punct { /// A string representation of the ident is available through the `to_string()` /// method. /// -/// ```edition2018 +/// ``` /// # use proc_macro2::{Ident, Span}; /// # /// # let ident = Ident::new("another_identifier", Span::call_site()); @@ -824,7 +819,7 @@ pub struct Ident { impl Ident { fn _new(inner: imp::Ident) -> Ident { Ident { - inner: inner, + inner, _marker: marker::PhantomData, } } @@ -856,7 +851,7 @@ impl Ident { /// Panics if the input string is neither a keyword nor a legal variable /// name. If you are not sure whether the string contains an identifier and /// need to handle an error case, use - /// <a href="https://docs.rs/syn/0.15/syn/fn.parse_str.html"><code + /// <a href="https://docs.rs/syn/1.0/syn/fn.parse_str.html"><code /// style="padding-right:0;">syn::parse_str</code></a><code /// style="padding-left:0;">::<Ident></code> /// rather than `Ident::new`. @@ -992,7 +987,7 @@ macro_rules! unsuffixed_int_literals { impl Literal { fn _new(inner: imp::Literal) -> Literal { Literal { - inner: inner, + inner, _marker: marker::PhantomData, } } @@ -1009,18 +1004,14 @@ impl Literal { u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, + u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, - isize_suffixed => isize, - } - - #[cfg(u128)] - suffixed_int_literals! { - u128_suffixed => u128, i128_suffixed => i128, + isize_suffixed => isize, } unsuffixed_int_literals! { @@ -1028,25 +1019,47 @@ impl Literal { u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, + u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, - isize_unsuffixed => isize, - } - - #[cfg(u128)] - unsuffixed_int_literals! { - u128_unsuffixed => u128, i128_unsuffixed => i128, + isize_unsuffixed => isize, } + /// Creates a new unsuffixed floating-point literal. + /// + /// This constructor is similar to those like `Literal::i8_unsuffixed` where + /// the float's value is emitted directly into the token but no suffix is + /// used, so it may be inferred to be a `f64` later in the compiler. + /// Literals created from negative numbers may not survive rountrips through + /// `TokenStream` or strings and may be broken into two tokens (`-` and + /// positive literal). + /// + /// # Panics + /// + /// This function requires that the specified float is finite, for example + /// if it is infinity or NaN this function will panic. pub fn f64_unsuffixed(f: f64) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f64_unsuffixed(f)) } + /// Creates a new suffixed floating-point literal. + /// + /// This constructor will create a literal like `1.0f64` where the value + /// specified is the preceding part of the token and `f64` is the suffix of + /// the token. This token will always be inferred to be an `f64` in the + /// compiler. Literals created from negative numbers may not survive + /// rountrips through `TokenStream` or strings and may be broken into two + /// tokens (`-` and positive literal). + /// + /// # Panics + /// + /// This function requires that the specified float is finite, for example + /// if it is infinity or NaN this function will panic. pub fn f64_suffixed(f: f64) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f64_suffixed(f)) @@ -1070,30 +1083,61 @@ impl Literal { Literal::_new(imp::Literal::f32_unsuffixed(f)) } + /// Creates a new suffixed floating-point literal. + /// + /// This constructor will create a literal like `1.0f32` where the value + /// specified is the preceding part of the token and `f32` is the suffix of + /// the token. This token will always be inferred to be an `f32` in the + /// compiler. Literals created from negative numbers may not survive + /// rountrips through `TokenStream` or strings and may be broken into two + /// tokens (`-` and positive literal). + /// + /// # Panics + /// + /// This function requires that the specified float is finite, for example + /// if it is infinity or NaN this function will panic. pub fn f32_suffixed(f: f32) -> Literal { assert!(f.is_finite()); Literal::_new(imp::Literal::f32_suffixed(f)) } + /// String literal. pub fn string(string: &str) -> Literal { Literal::_new(imp::Literal::string(string)) } + /// Character literal. pub fn character(ch: char) -> Literal { Literal::_new(imp::Literal::character(ch)) } + /// Byte string literal. pub fn byte_string(s: &[u8]) -> Literal { Literal::_new(imp::Literal::byte_string(s)) } + /// Returns the span encompassing this literal. pub fn span(&self) -> Span { Span::_new(self.inner.span()) } + /// Configures the span associated for this literal. pub fn set_span(&mut self, span: Span) { self.inner.set_span(span.inner); } + + /// Returns a `Span` that is a subset of `self.span()` containing only + /// the source bytes in range `range`. Returns `None` if the would-be + /// trimmed span is outside the bounds of `self`. + /// + /// Warning: the underlying [`proc_macro::Literal::subspan`] method is + /// nightly-only. When called from within a procedural macro not using a + /// nightly compiler, this method will always return `None`. + /// + /// [`proc_macro::Literal::subspan`]: https://doc.rust-lang.org/proc_macro/struct.Literal.html#method.subspan + pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { + self.inner.subspan(range).map(Span::_new) + } } impl fmt::Debug for Literal { @@ -1114,9 +1158,8 @@ pub mod token_stream { use std::marker; use std::rc::Rc; - use imp; - pub use TokenStream; - use TokenTree; + pub use crate::TokenStream; + use crate::{imp, TokenTree}; /// An iterator over `TokenStream`'s `TokenTree`s. /// diff --git a/src/strnom.rs b/src/strnom.rs index 96789d5..eb7d0b8 100644 --- a/src/strnom.rs +++ b/src/strnom.rs @@ -1,11 +1,9 @@ //! Adapted from [`nom`](https://github.com/Geal/nom). +use crate::fallback::LexError; use std::str::{Bytes, CharIndices, Chars}; - use unicode_xid::UnicodeXID; -use fallback::LexError; - #[derive(Copy, Clone, Eq, PartialEq)] pub struct Cursor<'a> { pub rest: &'a str, @@ -95,7 +93,7 @@ pub fn whitespace(input: Cursor) -> PResult<()> { } } match bytes[i] { - b' ' | 0x09...0x0d => { + b' ' | 0x09..=0x0d => { i += 1; continue; } diff --git a/src/wrapper.rs b/src/wrapper.rs index 994ed24..c3b6e3a 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -1,14 +1,12 @@ use std::fmt; use std::iter; +use std::ops::RangeBounds; use std::panic::{self, PanicInfo}; #[cfg(super_unstable)] use std::path::PathBuf; use std::str::FromStr; -use fallback; -use proc_macro; - -use {Delimiter, Punct, Spacing, TokenTree}; +use crate::{fallback, Delimiter, Punct, Spacing, TokenTree}; #[derive(Clone)] pub enum TokenStream { @@ -25,8 +23,7 @@ fn nightly_works() -> bool { use std::sync::atomic::*; use std::sync::Once; - #[allow(deprecated)] - static WORKS: AtomicUsize = ATOMIC_USIZE_INIT; + static WORKS: AtomicUsize = AtomicUsize::new(0); static INIT: Once = Once::new(); match WORKS.load(Ordering::SeqCst) { @@ -60,7 +57,7 @@ fn nightly_works() -> bool { // not occur, they need to call e.g. `proc_macro2::Span::call_site()` from // the main thread before launching any other threads. INIT.call_once(|| { - type PanicHook = Fn(&PanicInfo) + Sync + Send + 'static; + type PanicHook = dyn Fn(&PanicInfo) + Sync + Send + 'static; let null_hook: Box<PanicHook> = Box::new(|_panic_info| { /* ignore */ }); let sanity_check = &*null_hook as *const PanicHook; @@ -200,17 +197,6 @@ impl iter::FromIterator<TokenStream> for TokenStream { fn from_iter<I: IntoIterator<Item = TokenStream>>(streams: I) -> Self { let mut streams = streams.into_iter(); match streams.next() { - #[cfg(slow_extend)] - Some(TokenStream::Compiler(first)) => { - let stream = iter::once(first) - .chain(streams.map(|s| match s { - TokenStream::Compiler(s) => s, - TokenStream::Fallback(_) => mismatch(), - })) - .collect(); - TokenStream::Compiler(stream) - } - #[cfg(not(slow_extend))] Some(TokenStream::Compiler(mut first)) => { first.extend(streams.map(|s| match s { TokenStream::Compiler(s) => s, @@ -234,27 +220,11 @@ impl Extend<TokenTree> for TokenStream { fn extend<I: IntoIterator<Item = TokenTree>>(&mut self, streams: I) { match self { TokenStream::Compiler(tts) => { - #[cfg(not(slow_extend))] - { - tts.extend( - streams - .into_iter() - .map(|t| TokenStream::from(t).unwrap_nightly()), - ); - } - #[cfg(slow_extend)] - { - *tts = - tts.clone() - .into_iter() - .chain(streams.into_iter().map(TokenStream::from).flat_map( - |t| match t { - TokenStream::Compiler(tts) => tts.into_iter(), - _ => mismatch(), - }, - )) - .collect(); - } + tts.extend( + streams + .into_iter() + .map(|t| TokenStream::from(t).unwrap_nightly()), + ); } TokenStream::Fallback(tts) => tts.extend(streams), } @@ -345,18 +315,18 @@ impl Iterator for TokenTreeIter { TokenTreeIter::Fallback(iter) => return iter.next(), }; Some(match token { - proc_macro::TokenTree::Group(tt) => ::Group::_new(Group::Compiler(tt)).into(), + proc_macro::TokenTree::Group(tt) => crate::Group::_new(Group::Compiler(tt)).into(), proc_macro::TokenTree::Punct(tt) => { let spacing = match tt.spacing() { proc_macro::Spacing::Joint => Spacing::Joint, proc_macro::Spacing::Alone => Spacing::Alone, }; let mut o = Punct::new(tt.as_char(), spacing); - o.set_span(::Span::_new(Span::Compiler(tt.span()))); + o.set_span(crate::Span::_new(Span::Compiler(tt.span()))); o.into() } - proc_macro::TokenTree::Ident(s) => ::Ident::_new(Ident::Compiler(s)).into(), - proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Compiler(l)).into(), + proc_macro::TokenTree::Ident(s) => crate::Ident::_new(Ident::Compiler(s)).into(), + proc_macro::TokenTree::Literal(l) => crate::Literal::_new(Literal::Compiler(l)).into(), }) } @@ -510,9 +480,9 @@ impl Span { } } - #[cfg(super_unstable)] pub fn join(&self, other: Span) -> Option<Span> { let ret = match (self, other) { + #[cfg(proc_macro_span)] (Span::Compiler(a), Span::Compiler(b)) => Span::Compiler(a.join(b)?), (Span::Fallback(a), Span::Fallback(b)) => Span::Fallback(a.join(b)?), _ => return None, @@ -537,9 +507,9 @@ impl Span { } } -impl From<proc_macro::Span> for ::Span { - fn from(proc_span: proc_macro::Span) -> ::Span { - ::Span::_new(Span::Compiler(proc_span)) +impl From<proc_macro::Span> for crate::Span { + fn from(proc_span: proc_macro::Span) -> crate::Span { + crate::Span::_new(Span::Compiler(proc_span)) } } @@ -617,18 +587,22 @@ impl Group { } } - #[cfg(super_unstable)] pub fn span_open(&self) -> Span { match self { + #[cfg(proc_macro_span)] Group::Compiler(g) => Span::Compiler(g.span_open()), + #[cfg(not(proc_macro_span))] + Group::Compiler(g) => Span::Compiler(g.span()), Group::Fallback(g) => Span::Fallback(g.span_open()), } } - #[cfg(super_unstable)] pub fn span_close(&self) -> Span { match self { + #[cfg(proc_macro_span)] Group::Compiler(g) => Span::Compiler(g.span_close()), + #[cfg(not(proc_macro_span))] + Group::Compiler(g) => Span::Compiler(g.span()), Group::Fallback(g) => Span::Fallback(g.span_close()), } } @@ -804,40 +778,32 @@ impl Literal { u16_suffixed => u16, u32_suffixed => u32, u64_suffixed => u64, + u128_suffixed => u128, usize_suffixed => usize, i8_suffixed => i8, i16_suffixed => i16, i32_suffixed => i32, i64_suffixed => i64, + i128_suffixed => i128, isize_suffixed => isize, f32_suffixed => f32, f64_suffixed => f64, } - #[cfg(u128)] - suffixed_numbers! { - i128_suffixed => i128, - u128_suffixed => u128, - } - unsuffixed_integers! { u8_unsuffixed => u8, u16_unsuffixed => u16, u32_unsuffixed => u32, u64_unsuffixed => u64, + u128_unsuffixed => u128, usize_unsuffixed => usize, i8_unsuffixed => i8, i16_unsuffixed => i16, i32_unsuffixed => i32, i64_unsuffixed => i64, - isize_unsuffixed => isize, - } - - #[cfg(u128)] - unsuffixed_integers! { i128_unsuffixed => i128, - u128_unsuffixed => u128, + isize_unsuffixed => isize, } pub fn f32_unsuffixed(f: f32) -> Literal { @@ -895,6 +861,16 @@ impl Literal { } } + pub fn subspan<R: RangeBounds<usize>>(&self, range: R) -> Option<Span> { + match self { + #[cfg(proc_macro_span)] + Literal::Compiler(lit) => lit.subspan(range).map(Span::Compiler), + #[cfg(not(proc_macro_span))] + Literal::Compiler(_lit) => None, + Literal::Fallback(lit) => lit.subspan(range).map(Span::Fallback), + } + } + fn unwrap_nightly(self) -> proc_macro::Literal { match self { Literal::Compiler(s) => s, diff --git a/tests/features.rs b/tests/features.rs new file mode 100644 index 0000000..073f6e6 --- /dev/null +++ b/tests/features.rs @@ -0,0 +1,8 @@ +#[test] +#[ignore] +fn make_sure_no_proc_macro() { + assert!( + !cfg!(feature = "proc-macro"), + "still compiled with proc_macro?" + ); +} diff --git a/tests/marker.rs b/tests/marker.rs index 7bb5027..7af2539 100644 --- a/tests/marker.rs +++ b/tests/marker.rs @@ -1,5 +1,3 @@ -extern crate proc_macro2; - use proc_macro2::*; macro_rules! assert_impl { diff --git a/tests/test.rs b/tests/test.rs index 370392b..7528388 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -1,5 +1,3 @@ -extern crate proc_macro2; - use std::str::{self, FromStr}; use proc_macro2::{Ident, Literal, Spacing, Span, TokenStream, TokenTree}; @@ -99,6 +97,22 @@ fn literal_float() { } #[test] +fn literal_suffix() { + fn token_count(p: &str) -> usize { + p.parse::<TokenStream>().unwrap().into_iter().count() + } + + assert_eq!(token_count("999u256"), 1); + assert_eq!(token_count("999r#u256"), 3); + assert_eq!(token_count("1."), 1); + assert_eq!(token_count("1.f32"), 3); + assert_eq!(token_count("1.0_0"), 1); + assert_eq!(token_count("1._0"), 3); + assert_eq!(token_count("1._m"), 3); + assert_eq!(token_count("\"\"s"), 1); +} + +#[test] fn roundtrip() { fn roundtrip(p: &str) { println!("parse: {}", p); @@ -125,6 +139,9 @@ fn roundtrip() { 9 0 0xffffffffffffffffffffffffffffffff + 1x + 1u80 + 1f320 ", ); roundtrip("'a"); @@ -141,9 +158,6 @@ fn fail() { panic!("should have failed to parse: {}\n{:#?}", p, s); } } - fail("1x"); - fail("1u80"); - fail("1f320"); fail("' static"); fail("r#1"); fail("r#_"); |