proc_macro: remove the __internal module.
This commit is contained in:
parent
e305994beb
commit
38fee305da
4 changed files with 66 additions and 154 deletions
|
|
@ -1145,101 +1145,3 @@ impl fmt::Debug for Literal {
|
|||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Permanently unstable internal implementation details of this crate. This
|
||||
/// should not be used.
|
||||
///
|
||||
/// These methods are used by the rest of the compiler to generate instances of
|
||||
/// `TokenStream` to hand to macro definitions, as well as consume the output.
|
||||
///
|
||||
/// Note that this module is also intentionally separate from the rest of the
|
||||
/// crate. This allows the `#[unstable]` directive below to naturally apply to
|
||||
/// all of the contents.
|
||||
#[unstable(feature = "proc_macro_internals", issue = "27812")]
|
||||
#[doc(hidden)]
|
||||
pub mod __internal {
|
||||
use std::cell::Cell;
|
||||
use std::ptr;
|
||||
|
||||
use syntax::errors::DiagnosticBuilder;
|
||||
use syntax::ext::base::ExtCtxt;
|
||||
use syntax::parse::ParseSess;
|
||||
use syntax_pos::{BytePos, Loc, DUMMY_SP, Span};
|
||||
use syntax_pos::hygiene::{SyntaxContext, Transparency};
|
||||
|
||||
use super::LexError;
|
||||
|
||||
pub fn lookup_char_pos(pos: BytePos) -> Loc {
|
||||
with_sess(|sess, _| sess.source_map().lookup_char_pos(pos))
|
||||
}
|
||||
|
||||
pub fn parse_to_lex_err(mut err: DiagnosticBuilder) -> LexError {
|
||||
err.cancel();
|
||||
LexError { _inner: () }
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct ProcMacroData {
|
||||
pub def_site: Span,
|
||||
pub call_site: Span,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct ProcMacroSess {
|
||||
parse_sess: *const ParseSess,
|
||||
data: ProcMacroData,
|
||||
}
|
||||
|
||||
// Emulate scoped_thread_local!() here essentially
|
||||
thread_local! {
|
||||
static CURRENT_SESS: Cell<ProcMacroSess> = Cell::new(ProcMacroSess {
|
||||
parse_sess: ptr::null(),
|
||||
data: ProcMacroData { def_site: DUMMY_SP, call_site: DUMMY_SP },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_sess<F, R>(cx: &ExtCtxt, f: F) -> R
|
||||
where F: FnOnce() -> R
|
||||
{
|
||||
struct Reset { prev: ProcMacroSess }
|
||||
|
||||
impl Drop for Reset {
|
||||
fn drop(&mut self) {
|
||||
CURRENT_SESS.with(|p| p.set(self.prev));
|
||||
}
|
||||
}
|
||||
|
||||
CURRENT_SESS.with(|p| {
|
||||
let _reset = Reset { prev: p.get() };
|
||||
|
||||
// No way to determine def location for a proc macro right now, so use call location.
|
||||
let location = cx.current_expansion.mark.expn_info().unwrap().call_site;
|
||||
let to_span = |transparency| location.with_ctxt(
|
||||
SyntaxContext::empty().apply_mark_with_transparency(cx.current_expansion.mark,
|
||||
transparency));
|
||||
p.set(ProcMacroSess {
|
||||
parse_sess: cx.parse_sess,
|
||||
data: ProcMacroData {
|
||||
def_site: to_span(Transparency::Opaque),
|
||||
call_site: to_span(Transparency::Transparent),
|
||||
},
|
||||
});
|
||||
f()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn in_sess() -> bool
|
||||
{
|
||||
!CURRENT_SESS.with(|sess| sess.get()).parse_sess.is_null()
|
||||
}
|
||||
|
||||
pub fn with_sess<F, R>(f: F) -> R
|
||||
where F: FnOnce(&ParseSess, &ProcMacroData) -> R
|
||||
{
|
||||
let sess = CURRENT_SESS.with(|sess| sess.get());
|
||||
if sess.parse_sess.is_null() {
|
||||
panic!("procedural macro API is used outside of a procedural macro");
|
||||
}
|
||||
f(unsafe { &*sess.parse_sess }, &sess.data)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,16 +9,18 @@
|
|||
// except according to those terms.
|
||||
|
||||
use bridge::{server, TokenTree};
|
||||
use {Delimiter, Level, LineColumn, Spacing, __internal};
|
||||
use {Delimiter, Level, LineColumn, Spacing};
|
||||
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_errors::{self as errors, Diagnostic, DiagnosticBuilder};
|
||||
use std::ascii;
|
||||
use std::ops::Bound;
|
||||
use syntax::ast;
|
||||
use syntax::ext::base::ExtCtxt;
|
||||
use syntax::parse::lexer::comments;
|
||||
use syntax::parse::{self, token};
|
||||
use syntax::parse::{self, token, ParseSess};
|
||||
use syntax::tokenstream::{self, DelimSpan, TokenStream};
|
||||
use syntax_pos::hygiene::{SyntaxContext, Transparency};
|
||||
use syntax_pos::symbol::{keywords, Symbol};
|
||||
use syntax_pos::{BytePos, FileName, MultiSpan, Pos, SourceFile, Span};
|
||||
|
||||
|
|
@ -43,7 +45,7 @@ impl Delimiter {
|
|||
}
|
||||
|
||||
impl TokenTree<Group, Punct, Ident, Literal> {
|
||||
fn from_internal(stream: TokenStream, stack: &mut Vec<Self>) -> Self {
|
||||
fn from_internal(stream: TokenStream, sess: &ParseSess, stack: &mut Vec<Self>) -> Self {
|
||||
use syntax::parse::token::*;
|
||||
|
||||
let (tree, joint) = stream.as_tree();
|
||||
|
|
@ -188,14 +190,14 @@ impl TokenTree<Group, Punct, Ident, Literal> {
|
|||
})
|
||||
}
|
||||
|
||||
Interpolated(_) => __internal::with_sess(|sess, _| {
|
||||
Interpolated(_) => {
|
||||
let stream = token.interpolated_to_tokenstream(sess, span);
|
||||
TokenTree::Group(Group {
|
||||
delimiter: Delimiter::None,
|
||||
stream,
|
||||
span: DelimSpan::from_single(span),
|
||||
})
|
||||
}),
|
||||
}
|
||||
|
||||
DotEq => op!('.', '='),
|
||||
OpenDelim(..) | CloseDelim(..) => unreachable!(),
|
||||
|
|
@ -337,9 +339,31 @@ pub struct Literal {
|
|||
span: Span,
|
||||
}
|
||||
|
||||
pub struct Rustc;
|
||||
pub struct Rustc<'a> {
|
||||
sess: &'a ParseSess,
|
||||
def_site: Span,
|
||||
call_site: Span,
|
||||
}
|
||||
|
||||
impl server::Types for Rustc {
|
||||
impl<'a> Rustc<'a> {
|
||||
pub fn new(cx: &'a ExtCtxt) -> Self {
|
||||
// No way to determine def location for a proc macro right now, so use call location.
|
||||
let location = cx.current_expansion.mark.expn_info().unwrap().call_site;
|
||||
let to_span = |transparency| {
|
||||
location.with_ctxt(
|
||||
SyntaxContext::empty()
|
||||
.apply_mark_with_transparency(cx.current_expansion.mark, transparency),
|
||||
)
|
||||
};
|
||||
Rustc {
|
||||
sess: cx.parse_sess,
|
||||
def_site: to_span(Transparency::Opaque),
|
||||
call_site: to_span(Transparency::Transparent),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl server::Types for Rustc<'_> {
|
||||
type TokenStream = TokenStream;
|
||||
type TokenStreamBuilder = tokenstream::TokenStreamBuilder;
|
||||
type TokenStreamIter = TokenStreamIter;
|
||||
|
|
@ -353,7 +377,7 @@ impl server::Types for Rustc {
|
|||
type Span = Span;
|
||||
}
|
||||
|
||||
impl server::TokenStream for Rustc {
|
||||
impl server::TokenStream for Rustc<'_> {
|
||||
fn new(&mut self) -> Self::TokenStream {
|
||||
TokenStream::empty()
|
||||
}
|
||||
|
|
@ -361,14 +385,12 @@ impl server::TokenStream for Rustc {
|
|||
stream.is_empty()
|
||||
}
|
||||
fn from_str(&mut self, src: &str) -> Self::TokenStream {
|
||||
::__internal::with_sess(|sess, data| {
|
||||
parse::parse_stream_from_source_str(
|
||||
FileName::ProcMacroSourceCode,
|
||||
src.to_string(),
|
||||
sess,
|
||||
Some(data.call_site),
|
||||
)
|
||||
})
|
||||
parse::parse_stream_from_source_str(
|
||||
FileName::ProcMacroSourceCode,
|
||||
src.to_string(),
|
||||
self.sess,
|
||||
Some(self.call_site),
|
||||
)
|
||||
}
|
||||
fn to_string(&mut self, stream: &Self::TokenStream) -> String {
|
||||
stream.to_string()
|
||||
|
|
@ -387,7 +409,7 @@ impl server::TokenStream for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::TokenStreamBuilder for Rustc {
|
||||
impl server::TokenStreamBuilder for Rustc<'_> {
|
||||
fn new(&mut self) -> Self::TokenStreamBuilder {
|
||||
tokenstream::TokenStreamBuilder::new()
|
||||
}
|
||||
|
|
@ -399,7 +421,7 @@ impl server::TokenStreamBuilder for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::TokenStreamIter for Rustc {
|
||||
impl server::TokenStreamIter for Rustc<'_> {
|
||||
fn next(
|
||||
&mut self,
|
||||
iter: &mut Self::TokenStreamIter,
|
||||
|
|
@ -407,7 +429,7 @@ impl server::TokenStreamIter for Rustc {
|
|||
loop {
|
||||
let tree = iter.stack.pop().or_else(|| {
|
||||
let next = iter.cursor.next_as_stream()?;
|
||||
Some(TokenTree::from_internal(next, &mut iter.stack))
|
||||
Some(TokenTree::from_internal(next, self.sess, &mut iter.stack))
|
||||
})?;
|
||||
// HACK: The condition "dummy span + group with empty delimiter" represents an AST
|
||||
// fragment approximately converted into a token stream. This may happen, for
|
||||
|
|
@ -426,7 +448,7 @@ impl server::TokenStreamIter for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::Group for Rustc {
|
||||
impl server::Group for Rustc<'_> {
|
||||
fn new(&mut self, delimiter: Delimiter, stream: Self::TokenStream) -> Self::Group {
|
||||
Group {
|
||||
delimiter,
|
||||
|
|
@ -454,7 +476,7 @@ impl server::Group for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::Punct for Rustc {
|
||||
impl server::Punct for Rustc<'_> {
|
||||
fn new(&mut self, ch: char, spacing: Spacing) -> Self::Punct {
|
||||
Punct {
|
||||
ch,
|
||||
|
|
@ -480,7 +502,7 @@ impl server::Punct for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::Ident for Rustc {
|
||||
impl server::Ident for Rustc<'_> {
|
||||
fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
|
||||
let sym = Symbol::intern(string);
|
||||
if is_raw
|
||||
|
|
@ -499,7 +521,7 @@ impl server::Ident for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::Literal for Rustc {
|
||||
impl server::Literal for Rustc<'_> {
|
||||
// FIXME(eddyb) `Literal` should not expose internal `Debug` impls.
|
||||
fn debug(&mut self, literal: &Self::Literal) -> String {
|
||||
format!("{:?}", literal)
|
||||
|
|
@ -616,7 +638,7 @@ impl server::Literal for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::SourceFile for Rustc {
|
||||
impl<'a> server::SourceFile for Rustc<'a> {
|
||||
fn eq(&mut self, file1: &Self::SourceFile, file2: &Self::SourceFile) -> bool {
|
||||
Lrc::ptr_eq(file1, file2)
|
||||
}
|
||||
|
|
@ -634,7 +656,7 @@ impl server::SourceFile for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::MultiSpan for Rustc {
|
||||
impl server::MultiSpan for Rustc<'_> {
|
||||
fn new(&mut self) -> Self::MultiSpan {
|
||||
vec![]
|
||||
}
|
||||
|
|
@ -643,7 +665,7 @@ impl server::MultiSpan for Rustc {
|
|||
}
|
||||
}
|
||||
|
||||
impl server::Diagnostic for Rustc {
|
||||
impl server::Diagnostic for Rustc<'_> {
|
||||
fn new(&mut self, level: Level, msg: &str, spans: Self::MultiSpan) -> Self::Diagnostic {
|
||||
let mut diag = Diagnostic::new(level.to_internal(), msg);
|
||||
diag.set_span(MultiSpan::from_spans(spans));
|
||||
|
|
@ -659,24 +681,22 @@ impl server::Diagnostic for Rustc {
|
|||
diag.sub(level.to_internal(), msg, MultiSpan::from_spans(spans), None);
|
||||
}
|
||||
fn emit(&mut self, diag: Self::Diagnostic) {
|
||||
::__internal::with_sess(move |sess, _| {
|
||||
DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, diag).emit()
|
||||
});
|
||||
DiagnosticBuilder::new_diagnostic(&self.sess.span_diagnostic, diag).emit()
|
||||
}
|
||||
}
|
||||
|
||||
impl server::Span for Rustc {
|
||||
impl server::Span for Rustc<'_> {
|
||||
fn debug(&mut self, span: Self::Span) -> String {
|
||||
format!("{:?} bytes({}..{})", span.ctxt(), span.lo().0, span.hi().0)
|
||||
}
|
||||
fn def_site(&mut self) -> Self::Span {
|
||||
::__internal::with_sess(|_, data| data.def_site)
|
||||
self.def_site
|
||||
}
|
||||
fn call_site(&mut self) -> Self::Span {
|
||||
::__internal::with_sess(|_, data| data.call_site)
|
||||
self.call_site
|
||||
}
|
||||
fn source_file(&mut self, span: Self::Span) -> Self::SourceFile {
|
||||
::__internal::lookup_char_pos(span.lo()).file
|
||||
self.sess.source_map().lookup_char_pos(span.lo()).file
|
||||
}
|
||||
fn parent(&mut self, span: Self::Span) -> Option<Self::Span> {
|
||||
span.ctxt().outer().expn_info().map(|i| i.call_site)
|
||||
|
|
@ -685,22 +705,22 @@ impl server::Span for Rustc {
|
|||
span.source_callsite()
|
||||
}
|
||||
fn start(&mut self, span: Self::Span) -> LineColumn {
|
||||
let loc = ::__internal::lookup_char_pos(span.lo());
|
||||
let loc = self.sess.source_map().lookup_char_pos(span.lo());
|
||||
LineColumn {
|
||||
line: loc.line,
|
||||
column: loc.col.to_usize(),
|
||||
}
|
||||
}
|
||||
fn end(&mut self, span: Self::Span) -> LineColumn {
|
||||
let loc = ::__internal::lookup_char_pos(span.hi());
|
||||
let loc = self.sess.source_map().lookup_char_pos(span.hi());
|
||||
LineColumn {
|
||||
line: loc.line,
|
||||
column: loc.col.to_usize(),
|
||||
}
|
||||
}
|
||||
fn join(&mut self, first: Self::Span, second: Self::Span) -> Option<Self::Span> {
|
||||
let self_loc = ::__internal::lookup_char_pos(first.lo());
|
||||
let other_loc = ::__internal::lookup_char_pos(second.lo());
|
||||
let self_loc = self.sess.source_map().lookup_char_pos(first.lo());
|
||||
let other_loc = self.sess.source_map().lookup_char_pos(second.lo());
|
||||
|
||||
if self_loc.file.name != other_loc.file.name {
|
||||
return None;
|
||||
|
|
|
|||
|
|
@ -77,12 +77,9 @@ impl MultiItemModifier for ProcMacroDerive {
|
|||
let item = ecx.resolver.eliminate_crate_var(item);
|
||||
let token = Token::interpolated(token::NtItem(item));
|
||||
let input = tokenstream::TokenTree::Token(DUMMY_SP, token).into();
|
||||
let server = ::proc_macro::rustc::Rustc;
|
||||
let res = ::proc_macro::__internal::set_sess(ecx, || {
|
||||
self.client.run(&EXEC_STRATEGY, server, input)
|
||||
});
|
||||
|
||||
let stream = match res {
|
||||
let server = ::proc_macro::rustc::Rustc::new(ecx);
|
||||
let stream = match self.client.run(&EXEC_STRATEGY, server, input) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
let msg = "proc-macro derive panicked";
|
||||
|
|
@ -103,13 +100,14 @@ impl MultiItemModifier for ProcMacroDerive {
|
|||
let mut items = vec![];
|
||||
|
||||
loop {
|
||||
match parser.parse_item().map_err(::proc_macro::__internal::parse_to_lex_err) {
|
||||
match parser.parse_item() {
|
||||
Ok(None) => break,
|
||||
Ok(Some(item)) => {
|
||||
items.push(Annotatable::Item(item))
|
||||
}
|
||||
Err(_) => {
|
||||
Err(mut err) => {
|
||||
// FIXME: handle this better
|
||||
err.cancel();
|
||||
ecx.struct_span_fatal(span, msg).emit();
|
||||
FatalError.raise();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,12 +32,8 @@ impl base::AttrProcMacro for AttrProcMacro {
|
|||
annotation: TokenStream,
|
||||
annotated: TokenStream)
|
||||
-> TokenStream {
|
||||
let server = ::proc_macro::rustc::Rustc;
|
||||
let res = ::proc_macro::__internal::set_sess(ecx, || {
|
||||
self.client.run(&EXEC_STRATEGY, server, annotation, annotated)
|
||||
});
|
||||
|
||||
match res {
|
||||
let server = ::proc_macro::rustc::Rustc::new(ecx);
|
||||
match self.client.run(&EXEC_STRATEGY, server, annotation, annotated) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
let msg = "custom attribute panicked";
|
||||
|
|
@ -65,12 +61,8 @@ impl base::ProcMacro for BangProcMacro {
|
|||
span: Span,
|
||||
input: TokenStream)
|
||||
-> TokenStream {
|
||||
let server = ::proc_macro::rustc::Rustc;
|
||||
let res = ::proc_macro::__internal::set_sess(ecx, || {
|
||||
self.client.run(&EXEC_STRATEGY, server, input)
|
||||
});
|
||||
|
||||
match res {
|
||||
let server = ::proc_macro::rustc::Rustc::new(ecx);
|
||||
match self.client.run(&EXEC_STRATEGY, server, input) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
let msg = "proc macro panicked";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue