1
Fork 0

proc_macro: stop using a remote object handle for Punct

This greatly reduces round-trips to fetch relevant extra information about the
token in proc macro code, and avoids RPC messages to create Punct tokens.
This commit is contained in:
Nika Layzell 2021-06-28 22:30:55 -04:00
parent 3b0d4813ab
commit 72bfe618fa
6 changed files with 49 additions and 95 deletions

View file

@ -14,8 +14,8 @@ use rustc_span::def_id::CrateNum;
use rustc_span::symbol::{self, kw, sym, Symbol}; use rustc_span::symbol::{self, kw, sym, Symbol};
use rustc_span::{BytePos, FileName, Pos, SourceFile, Span}; use rustc_span::{BytePos, FileName, Pos, SourceFile, Span};
use pm::bridge::{server, ExpnGlobals, TokenTree}; use pm::bridge::{server, ExpnGlobals, Punct, TokenTree};
use pm::{Delimiter, Level, LineColumn, Spacing}; use pm::{Delimiter, Level, LineColumn};
use std::ops::Bound; use std::ops::Bound;
use std::{ascii, panic}; use std::{ascii, panic};
@ -50,7 +50,7 @@ impl ToInternal<token::Delimiter> for Delimiter {
} }
impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)> impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)>
for TokenTree<Group, Punct, Ident, Literal> for TokenTree<Span, Group, Ident, Literal>
{ {
fn from_internal( fn from_internal(
((tree, spacing), stack, rustc): (TreeAndSpacing, &mut Vec<Self>, &mut Rustc<'_, '_>), ((tree, spacing), stack, rustc): (TreeAndSpacing, &mut Vec<Self>, &mut Rustc<'_, '_>),
@ -79,16 +79,16 @@ impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)>
} }
macro_rules! op { macro_rules! op {
($a:expr) => { ($a:expr) => {
tt!(Punct::new($a, joint)) tt!(Punct { ch: $a, joint })
}; };
($a:expr, $b:expr) => {{ ($a:expr, $b:expr) => {{
stack.push(tt!(Punct::new($b, joint))); stack.push(tt!(Punct { ch: $b, joint }));
tt!(Punct::new($a, true)) tt!(Punct { ch: $a, joint: true })
}}; }};
($a:expr, $b:expr, $c:expr) => {{ ($a:expr, $b:expr, $c:expr) => {{
stack.push(tt!(Punct::new($c, joint))); stack.push(tt!(Punct { ch: $c, joint }));
stack.push(tt!(Punct::new($b, true))); stack.push(tt!(Punct { ch: $b, joint: true }));
tt!(Punct::new($a, true)) tt!(Punct { ch: $a, joint: true })
}}; }};
} }
@ -146,7 +146,7 @@ impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)>
Lifetime(name) => { Lifetime(name) => {
let ident = symbol::Ident::new(name, span).without_first_quote(); let ident = symbol::Ident::new(name, span).without_first_quote();
stack.push(tt!(Ident::new(rustc.sess(), ident.name, false))); stack.push(tt!(Ident::new(rustc.sess(), ident.name, false)));
tt!(Punct::new('\'', true)) tt!(Punct { ch: '\'', joint: true })
} }
Literal(lit) => tt!(Literal { lit }), Literal(lit) => tt!(Literal { lit }),
DocComment(_, attr_style, data) => { DocComment(_, attr_style, data) => {
@ -169,9 +169,9 @@ impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)>
flatten: false, flatten: false,
})); }));
if attr_style == ast::AttrStyle::Inner { if attr_style == ast::AttrStyle::Inner {
stack.push(tt!(Punct::new('!', false))); stack.push(tt!(Punct { ch: '!', joint: false }));
} }
tt!(Punct::new('#', false)) tt!(Punct { ch: '#', joint: false })
} }
Interpolated(nt) if let NtIdent(ident, is_raw) = *nt => { Interpolated(nt) if let NtIdent(ident, is_raw) = *nt => {
@ -192,7 +192,7 @@ impl FromInternal<(TreeAndSpacing, &'_ mut Vec<Self>, &mut Rustc<'_, '_>)>
} }
} }
impl ToInternal<TokenStream> for TokenTree<Group, Punct, Ident, Literal> { impl ToInternal<TokenStream> for TokenTree<Span, Group, Ident, Literal> {
fn to_internal(self) -> TokenStream { fn to_internal(self) -> TokenStream {
use rustc_ast::token::*; use rustc_ast::token::*;
@ -288,27 +288,6 @@ pub struct Group {
flatten: bool, flatten: bool,
} }
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Punct {
ch: char,
// NB. not using `Spacing` here because it doesn't implement `Hash`.
joint: bool,
span: Span,
}
impl Punct {
fn new(ch: char, joint: bool, span: Span) -> Punct {
const LEGAL_CHARS: &[char] = &[
'=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^', '&', '|', '@', '.', ',', ';',
':', '#', '$', '?', '\'',
];
if !LEGAL_CHARS.contains(&ch) {
panic!("unsupported character `{:?}`", ch)
}
Punct { ch, joint, span }
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)] #[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct Ident { pub struct Ident {
sym: Symbol, sym: Symbol,
@ -378,7 +357,6 @@ impl server::Types for Rustc<'_, '_> {
type FreeFunctions = FreeFunctions; type FreeFunctions = FreeFunctions;
type TokenStream = TokenStream; type TokenStream = TokenStream;
type Group = Group; type Group = Group;
type Punct = Punct;
type Ident = Ident; type Ident = Ident;
type Literal = Literal; type Literal = Literal;
type SourceFile = Lrc<SourceFile>; type SourceFile = Lrc<SourceFile>;
@ -471,7 +449,7 @@ impl server::TokenStream for Rustc<'_, '_> {
fn from_token_tree( fn from_token_tree(
&mut self, &mut self,
tree: TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>, tree: TokenTree<Self::Span, Self::Group, Self::Ident, Self::Literal>,
) -> Self::TokenStream { ) -> Self::TokenStream {
tree.to_internal() tree.to_internal()
} }
@ -479,7 +457,7 @@ impl server::TokenStream for Rustc<'_, '_> {
fn concat_trees( fn concat_trees(
&mut self, &mut self,
base: Option<Self::TokenStream>, base: Option<Self::TokenStream>,
trees: Vec<TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>>, trees: Vec<TokenTree<Self::Span, Self::Group, Self::Ident, Self::Literal>>,
) -> Self::TokenStream { ) -> Self::TokenStream {
let mut builder = tokenstream::TokenStreamBuilder::new(); let mut builder = tokenstream::TokenStreamBuilder::new();
if let Some(base) = base { if let Some(base) = base {
@ -509,7 +487,7 @@ impl server::TokenStream for Rustc<'_, '_> {
fn into_trees( fn into_trees(
&mut self, &mut self,
stream: Self::TokenStream, stream: Self::TokenStream,
) -> Vec<TokenTree<Self::Group, Self::Punct, Self::Ident, Self::Literal>> { ) -> Vec<TokenTree<Self::Span, Self::Group, Self::Ident, Self::Literal>> {
// FIXME: This is a raw port of the previous approach (which had a // FIXME: This is a raw port of the previous approach (which had a
// `TokenStreamIter` server-side object with a single `next` method), // `TokenStreamIter` server-side object with a single `next` method),
// and can probably be optimized (for bulk conversion). // and can probably be optimized (for bulk conversion).
@ -577,28 +555,6 @@ impl server::Group for Rustc<'_, '_> {
} }
} }
impl server::Punct for Rustc<'_, '_> {
fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
Punct::new(ch, spacing == Spacing::Joint, self.call_site)
}
fn as_char(&mut self, punct: Self::Punct) -> char {
punct.ch
}
fn spacing(&mut self, punct: Self::Punct) -> Spacing {
if punct.joint { Spacing::Joint } else { Spacing::Alone }
}
fn span(&mut self, punct: Self::Punct) -> Self::Span {
punct.span
}
fn with_span(&mut self, punct: Self::Punct, span: Self::Span) -> Self::Punct {
Punct { span, ..punct }
}
}
impl server::Ident for Rustc<'_, '_> { impl server::Ident for Rustc<'_, '_> {
fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident { fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
Ident::new(self.sess(), Symbol::intern(string), is_raw, span) Ident::new(self.sess(), Symbol::intern(string), is_raw, span)

View file

@ -182,7 +182,6 @@ define_handles! {
Diagnostic, Diagnostic,
'interned: 'interned:
Punct,
Ident, Ident,
Span, Span,
} }

View file

@ -65,11 +65,11 @@ macro_rules! with_api {
fn from_str(src: &str) -> $S::TokenStream; fn from_str(src: &str) -> $S::TokenStream;
fn to_string($self: &$S::TokenStream) -> String; fn to_string($self: &$S::TokenStream) -> String;
fn from_token_tree( fn from_token_tree(
tree: TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>, tree: TokenTree<$S::Span, $S::Group, $S::Ident, $S::Literal>,
) -> $S::TokenStream; ) -> $S::TokenStream;
fn concat_trees( fn concat_trees(
base: Option<$S::TokenStream>, base: Option<$S::TokenStream>,
trees: Vec<TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>>, trees: Vec<TokenTree<$S::Span, $S::Group, $S::Ident, $S::Literal>>,
) -> $S::TokenStream; ) -> $S::TokenStream;
fn concat_streams( fn concat_streams(
base: Option<$S::TokenStream>, base: Option<$S::TokenStream>,
@ -77,7 +77,7 @@ macro_rules! with_api {
) -> $S::TokenStream; ) -> $S::TokenStream;
fn into_trees( fn into_trees(
$self: $S::TokenStream $self: $S::TokenStream
) -> Vec<TokenTree<$S::Group, $S::Punct, $S::Ident, $S::Literal>>; ) -> Vec<TokenTree<$S::Span, $S::Group, $S::Ident, $S::Literal>>;
}, },
Group { Group {
fn drop($self: $S::Group); fn drop($self: $S::Group);
@ -90,13 +90,6 @@ macro_rules! with_api {
fn span_close($self: &$S::Group) -> $S::Span; fn span_close($self: &$S::Group) -> $S::Span;
fn set_span($self: &mut $S::Group, span: $S::Span); fn set_span($self: &mut $S::Group, span: $S::Span);
}, },
Punct {
fn new(ch: char, spacing: Spacing) -> $S::Punct;
fn as_char($self: $S::Punct) -> char;
fn spacing($self: $S::Punct) -> Spacing;
fn span($self: $S::Punct) -> $S::Span;
fn with_span($self: $S::Punct, span: $S::Span) -> $S::Punct;
},
Ident { Ident {
fn new(string: &str, span: $S::Span, is_raw: bool) -> $S::Ident; fn new(string: &str, span: $S::Span, is_raw: bool) -> $S::Ident;
fn span($self: $S::Ident) -> $S::Span; fn span($self: $S::Ident) -> $S::Span;
@ -449,15 +442,24 @@ compound_traits!(
); );
#[derive(Clone)] #[derive(Clone)]
pub enum TokenTree<G, P, I, L> { pub struct Punct<S> {
pub ch: char,
pub joint: bool,
pub span: S,
}
compound_traits!(struct Punct<Sp> { ch, joint, span });
#[derive(Clone)]
pub enum TokenTree<S, G, I, L> {
Group(G), Group(G),
Punct(P), Punct(Punct<S>),
Ident(I), Ident(I),
Literal(L), Literal(L),
} }
compound_traits!( compound_traits!(
enum TokenTree<G, P, I, L> { enum TokenTree<Sp, G, I, L> {
Group(tt), Group(tt),
Punct(tt), Punct(tt),
Ident(tt), Ident(tt),

View file

@ -9,7 +9,6 @@ pub trait Types {
type FreeFunctions: 'static; type FreeFunctions: 'static;
type TokenStream: 'static + Clone; type TokenStream: 'static + Clone;
type Group: 'static + Clone; type Group: 'static + Clone;
type Punct: 'static + Copy + Eq + Hash;
type Ident: 'static + Copy + Eq + Hash; type Ident: 'static + Copy + Eq + Hash;
type Literal: 'static + Clone; type Literal: 'static + Clone;
type SourceFile: 'static + Clone; type SourceFile: 'static + Clone;

View file

@ -212,8 +212,8 @@ pub use quote::{quote, quote_span};
fn tree_to_bridge_tree( fn tree_to_bridge_tree(
tree: TokenTree, tree: TokenTree,
) -> bridge::TokenTree< ) -> bridge::TokenTree<
bridge::client::Span,
bridge::client::Group, bridge::client::Group,
bridge::client::Punct,
bridge::client::Ident, bridge::client::Ident,
bridge::client::Literal, bridge::client::Literal,
> { > {
@ -238,8 +238,8 @@ impl From<TokenTree> for TokenStream {
struct ConcatTreesHelper { struct ConcatTreesHelper {
trees: Vec< trees: Vec<
bridge::TokenTree< bridge::TokenTree<
bridge::client::Span,
bridge::client::Group, bridge::client::Group,
bridge::client::Punct,
bridge::client::Ident, bridge::client::Ident,
bridge::client::Literal, bridge::client::Literal,
>, >,
@ -365,8 +365,8 @@ pub mod token_stream {
pub struct IntoIter( pub struct IntoIter(
std::vec::IntoIter< std::vec::IntoIter<
bridge::TokenTree< bridge::TokenTree<
bridge::client::Span,
bridge::client::Group, bridge::client::Group,
bridge::client::Punct,
bridge::client::Ident, bridge::client::Ident,
bridge::client::Literal, bridge::client::Literal,
>, >,
@ -925,7 +925,7 @@ impl fmt::Debug for Group {
/// forms of `Spacing` returned. /// forms of `Spacing` returned.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
#[derive(Clone)] #[derive(Clone)]
pub struct Punct(bridge::client::Punct); pub struct Punct(bridge::Punct<bridge::client::Span>);
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl !Send for Punct {} impl !Send for Punct {}
@ -958,13 +958,20 @@ impl Punct {
/// which can be further configured with the `set_span` method below. /// which can be further configured with the `set_span` method below.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn new(ch: char, spacing: Spacing) -> Punct { pub fn new(ch: char, spacing: Spacing) -> Punct {
Punct(bridge::client::Punct::new(ch, spacing)) const LEGAL_CHARS: &[char] = &[
'=', '<', '>', '!', '~', '+', '-', '*', '/', '%', '^', '&', '|', '@', '.', ',', ';',
':', '#', '$', '?', '\'',
];
if !LEGAL_CHARS.contains(&ch) {
panic!("unsupported character `{:?}`", ch);
}
Punct(bridge::Punct { ch, joint: spacing == Spacing::Joint, span: Span::call_site().0 })
} }
/// Returns the value of this punctuation character as `char`. /// Returns the value of this punctuation character as `char`.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn as_char(&self) -> char { pub fn as_char(&self) -> char {
self.0.as_char() self.0.ch
} }
/// Returns the spacing of this punctuation character, indicating whether it's immediately /// Returns the spacing of this punctuation character, indicating whether it's immediately
@ -973,28 +980,19 @@ impl Punct {
/// (`Alone`) so the operator has certainly ended. /// (`Alone`) so the operator has certainly ended.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn spacing(&self) -> Spacing { pub fn spacing(&self) -> Spacing {
self.0.spacing() if self.0.joint { Spacing::Joint } else { Spacing::Alone }
} }
/// Returns the span for this punctuation character. /// Returns the span for this punctuation character.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn span(&self) -> Span { pub fn span(&self) -> Span {
Span(self.0.span()) Span(self.0.span)
} }
/// Configure the span for this punctuation character. /// Configure the span for this punctuation character.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
pub fn set_span(&mut self, span: Span) { pub fn set_span(&mut self, span: Span) {
self.0 = self.0.with_span(span.0); self.0.span = span.0;
}
}
// N.B., the bridge only provides `to_string`, implement `fmt::Display`
// based on it (the reverse of the usual relationship between the two).
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl ToString for Punct {
fn to_string(&self) -> String {
TokenStream::from(TokenTree::from(self.clone())).to_string()
} }
} }
@ -1003,7 +1001,7 @@ impl ToString for Punct {
#[stable(feature = "proc_macro_lib2", since = "1.29.0")] #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for Punct { impl fmt::Display for Punct {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.to_string()) write!(f, "{}", self.as_char())
} }
} }

View file

@ -2,7 +2,7 @@
// rustc-env:RUST_BACKTRACE=0 // rustc-env:RUST_BACKTRACE=0
// FIXME https://github.com/rust-lang/rust/issues/59998 // FIXME https://github.com/rust-lang/rust/issues/59998
// normalize-stderr-test "thread.*panicked.*proc_macro_server.rs.*\n" -> "" // normalize-stderr-test "thread.*panicked.*proc_macro.*lib.rs.*\n" -> ""
// normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> ""
// normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> "" // normalize-stderr-test "\nerror: internal compiler error.*\n\n" -> ""
// normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> "" // normalize-stderr-test "note:.*unexpectedly panicked.*\n\n" -> ""