proc_macro: remove the __internal module.

This commit is contained in:
Eduard-Mihai Burtescu 2018-03-19 22:44:24 +02:00
parent e305994beb
commit 38fee305da
4 changed files with 66 additions and 154 deletions

View file

@ -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)
}
}

View file

@ -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;

View file

@ -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();
}

View file

@ -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";