Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 2 additions & 30 deletions library/proc_macro/src/bridge/buffer.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
//! Buffer management for same-process client<->server communication.

use std::io::{self, Write};
use std::mem::{self, ManuallyDrop};
use std::ops::{Deref, DerefMut};
use std::ops::Deref;
use std::slice;

#[repr(C)]
Expand Down Expand Up @@ -32,13 +31,6 @@ impl Deref for Buffer {
}
}

impl DerefMut for Buffer {
#[inline]
fn deref_mut(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.data, self.len) }
}
}

impl Buffer {
#[inline]
pub(super) fn new() -> Self {
Expand Down Expand Up @@ -99,25 +91,6 @@ impl Buffer {
}
}

impl Write for Buffer {
#[inline]
fn write(&mut self, xs: &[u8]) -> io::Result<usize> {
self.extend_from_slice(xs);
Ok(xs.len())
}

#[inline]
fn write_all(&mut self, xs: &[u8]) -> io::Result<()> {
self.extend_from_slice(xs);
Ok(())
}

#[inline]
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}

impl Drop for Buffer {
#[inline]
fn drop(&mut self) {
Expand All @@ -128,8 +101,7 @@ impl Drop for Buffer {

impl From<Vec<u8>> for Buffer {
fn from(v: Vec<u8>) -> Self {
let mut v = ManuallyDrop::new(v);
let (data, len, capacity) = (v.as_mut_ptr(), v.len(), v.capacity());
let (data, len, capacity) = v.into_raw_parts();

// This utility function is nested in here because it can *only*
// be safely called on `Buffer`s created by *this* `proc_macro`.
Expand Down
2 changes: 1 addition & 1 deletion library/proc_macro/src/bridge/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ impl Client {
pub const fn expand1(f: impl Fn(crate::TokenStream) -> crate::TokenStream + Copy) -> Self {
Client {
run: super::selfless_reify::reify_to_extern_c_fn_hrt_bridge(move |bridge| {
run_client(bridge, |input| f(input))
run_client(bridge, f)
}),
}
}
Expand Down
3 changes: 1 addition & 2 deletions library/proc_macro/src/bridge/rpc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Serialization for client-server communication.

use std::io::Write;
use std::num::NonZero;

use super::buffer::Buffer;
Expand Down Expand Up @@ -209,7 +208,7 @@ impl<S> Encode<S> for &str {
fn encode(self, w: &mut Buffer, s: &mut S) {
let bytes = self.as_bytes();
bytes.len().encode(w, s);
w.write_all(bytes).unwrap();
w.extend_from_slice(bytes);
}
}

Expand Down
24 changes: 11 additions & 13 deletions library/proc_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
#![warn(unreachable_pub)]
#![deny(unsafe_op_in_unsafe_fn)]

#[unstable(feature = "proc_macro_internals", issue = "27812")]
#[unstable(feature = "proc_macro_internals", issue = "none")]
#[doc(hidden)]
pub mod bridge;

Expand Down Expand Up @@ -295,7 +295,7 @@ impl TokenStream {
/// Checks if this `TokenStream` is empty.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn is_empty(&self) -> bool {
self.0.as_ref().map(|h| BridgeMethods::ts_is_empty(h)).unwrap_or(true)
self.0.as_ref().map(BridgeMethods::ts_is_empty).unwrap_or(true)
}

/// Parses this `TokenStream` as an expression and attempts to expand any
Expand Down Expand Up @@ -574,9 +574,7 @@ pub mod token_stream {
type IntoIter = IntoIter;

fn into_iter(self) -> IntoIter {
IntoIter(
self.0.map(|v| BridgeMethods::ts_into_trees(v)).unwrap_or_default().into_iter(),
)
IntoIter(self.0.map(BridgeMethods::ts_into_trees).unwrap_or_default().into_iter())
}
}
}
Expand All @@ -594,7 +592,7 @@ pub macro quote($($t:tt)*) {
/* compiler built-in */
}

#[unstable(feature = "proc_macro_internals", issue = "27812")]
#[unstable(feature = "proc_macro_internals", issue = "none")]
#[doc(hidden)]
mod quote;

Expand Down Expand Up @@ -754,14 +752,14 @@ impl Span {

// Used by the implementation of `Span::quote`
#[doc(hidden)]
#[unstable(feature = "proc_macro_internals", issue = "27812")]
#[unstable(feature = "proc_macro_internals", issue = "none")]
pub fn save_span(&self) -> usize {
BridgeMethods::span_save_span(self.0)
}

// Used by the implementation of `Span::quote`
#[doc(hidden)]
#[unstable(feature = "proc_macro_internals", issue = "27812")]
#[unstable(feature = "proc_macro_internals", issue = "none")]
pub fn recover_proc_macro_span(id: usize) -> Span {
Span(BridgeMethods::span_recover_proc_macro_span(id))
}
Expand Down Expand Up @@ -1295,7 +1293,7 @@ macro_rules! unsuffixed_int_literals {
/// specified on this token, meaning that invocations like
/// `Literal::i8_unsuffixed(1)` are equivalent to
/// `Literal::u32_unsuffixed(1)`.
/// Literals created from negative numbers might not survive rountrips through
/// Literals created from negative numbers might not survive roundtrips through
/// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// Literals created through this method have the `Span::call_site()`
Expand Down Expand Up @@ -1415,7 +1413,7 @@ impl 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 might not survive rountrips through
/// Literals created from negative numbers might not survive roundtrips through
/// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// # Panics
Expand All @@ -1440,7 +1438,7 @@ impl Literal {
/// 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 might not survive rountrips through
/// Literals created from negative numbers might not survive roundtrips through
/// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// # Panics
Expand All @@ -1460,7 +1458,7 @@ impl 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 might not survive rountrips through
/// Literals created from negative numbers might not survive roundtrips through
/// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// # Panics
Expand All @@ -1485,7 +1483,7 @@ impl Literal {
/// 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 might not survive rountrips through
/// Literals created from negative numbers might not survive roundtrips through
/// `TokenStream` or strings and may be broken into two tokens (`-` and positive literal).
///
/// # Panics
Expand Down
33 changes: 27 additions & 6 deletions tests/ui/proc-macro/auxiliary/nonfatal-parsing-body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,38 @@ enum Mode {
OtherWithPanic,
}

fn print_unspanned<T>(s: &str) -> Result<T, LexError>
where
T: FromStr<Err = LexError> + Debug,
{
let t = T::from_str(s);
let mut s = format!("{t:?}");
while let Some((l, r)) = s.split_once("span: #") {
let (_, r) = r.split_once(")").unwrap();
s = format!("{l}span: Span{r}");
}
println!("{s}");
t
}

fn parse<T>(s: &str, mode: Mode)
where
T: FromStr<Err = LexError> + Debug,
{
match mode {
NormalOk => {
let t = T::from_str(s);
println!("{:?}", t);
let t = print_unspanned::<T>(s);
assert!(t.is_ok());
}
NormalErr => {
let t = T::from_str(s);
println!("{:?}", t);
let t = print_unspanned::<T>(s);
assert!(t.is_err());
}
OtherError => {
println!("{:?}", T::from_str(s));
print_unspanned::<T>(s);
}
OtherWithPanic => {
if catch_unwind(|| println!("{:?}", T::from_str(s))).is_ok() {
if catch_unwind(|| print_unspanned::<T>(s)).is_ok() {
eprintln!("{s} did not panic");
}
}
Expand Down Expand Up @@ -64,14 +76,18 @@ fn lit(s: &str, mode: Mode) {
}

pub fn run() {
assert_eq!("\'", "'");
// returns Ok(valid instance)
lit("r\"g\"", NormalOk);
lit("r#\"g\"#", NormalOk);
lit("123", NormalOk);
lit("\"ab\"", NormalOk);
lit("\'b\'", NormalOk);
lit("'b'", NormalOk);
lit("b\"b\"", NormalOk);
lit("c\"b\"", NormalOk);
lit("cr\"b\"", NormalOk);
lit("'\\''", NormalOk);
lit("b'b'", NormalOk);
lit("256u8", NormalOk);
lit("-256u8", NormalOk);
Expand Down Expand Up @@ -99,10 +115,13 @@ pub fn run() {
NormalOk,
);
stream("/*a*/ //", NormalOk);
lit("\"\"", NormalOk);
stream("", NormalOk);

println!("### ERRORS");

// returns Err(LexError)
lit("", NormalErr);
lit("\'c\'/**/", NormalErr);
lit(" 0", NormalErr);
lit("0 ", NormalErr);
Expand All @@ -119,10 +138,12 @@ pub fn run() {
// emits diagnostics and returns LexError
lit("r'r'", OtherError);
lit("c'r'", OtherError);
lit("\u{2000}", OtherError);

// emits diagnostic and returns a seemingly valid tokenstream
stream("r'r'", OtherError);
stream("c'r'", OtherError);
stream("\u{2000}", OtherError);

for parse in [stream as fn(&str, Mode), lit] {
// emits diagnostic(s), then panics
Expand Down
26 changes: 25 additions & 1 deletion tests/ui/proc-macro/nonfatal-parsing.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ help: consider inserting whitespace here
LL | c 'r'
| +

error: unknown start of token: \u{2000}
--> <proc-macro source code>:1:1
|
LL |  
| ^
|
help: Unicode character ' ' (En Quad) looks like ' ' (Space), but it is not
|
LL |
|

error: prefix `r` is unknown
--> $DIR/nonfatal-parsing.rs:15:5
|
Expand All @@ -40,6 +51,19 @@ LL | nonfatal_parsing::run!();
= note: prefixed identifiers and literals are reserved since Rust 2021
= note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)

error: unknown start of token: \u{2000}
--> $DIR/nonfatal-parsing.rs:15:5
|
LL | nonfatal_parsing::run!();
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: this error originates in the macro `nonfatal_parsing::run` (in Nightly builds, run with -Z macro-backtrace for more info)
help: Unicode character ' ' (En Quad) looks like ' ' (Space), but it is not
--> <proc-macro source code>:1:1
|
LL |
|

error: found invalid character; only `#` is allowed in raw string delimitation: \u{0}
--> $DIR/nonfatal-parsing.rs:15:5
|
Expand Down Expand Up @@ -175,6 +199,6 @@ error: invalid digit for a base 2 literal
LL | /*a*/ 0b2 //
| ^

error: aborting due to 20 previous errors
error: aborting due to 22 previous errors

For more information about this error, try `rustc --explain E0768`.
Loading
Loading