Skip to content

Commit 578c40e

Browse files
committed
proc_macro: move Term to the bridge.
1 parent a252474 commit 578c40e

File tree

3 files changed

+177
-92
lines changed

3 files changed

+177
-92
lines changed

src/libproc_macro/bridge.rs

+104-25
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@
2121
2222
use std::cell::Cell;
2323
use std::fmt;
24+
use std::ops::Deref;
2425
use std::path::PathBuf;
2526
use std::ptr::NonNull;
2627

27-
use self::storage::{FromConcrete, ToConcrete};
28+
use self::storage::{FromConcrete, ToConcrete, Storage};
2829

2930
mod generation {
3031
use std::cell::Cell;
@@ -233,14 +234,39 @@ mod storage {
233234
}
234235
}
235236

237+
/// Thread-local reference, to be used in place of `&'static T`
238+
/// when it shouldn't be allowed to escape the thread.
239+
#[repr(C)]
240+
#[derive(Copy, Clone)]
241+
pub struct ThreadRef<T: ?Sized + 'static>(&'static T);
242+
243+
impl<T: ?Sized + 'static> !Send for ThreadRef<T> {}
244+
impl<T: ?Sized + 'static> !Sync for ThreadRef<T> {}
245+
246+
impl<T: ?Sized + 'static> Deref for ThreadRef<T> {
247+
type Target = T;
248+
fn deref(&self) -> &T {
249+
self.0
250+
}
251+
}
252+
253+
impl<T: ?Sized + 'static> ThreadRef<T> {
254+
pub fn new(x: &'static T) -> Self {
255+
ThreadRef(x)
256+
}
257+
}
258+
236259
storage_concrete_passthrough! {
237260
[] (),
238261
[] bool,
262+
[] char,
239263
['a] &'a str,
264+
[] ThreadRef<str>,
240265

241266
// FIXME(eddyb) achieve ABI compatibility for these types.
242-
[] ::TokenNode,
243267
[] ::Delimiter,
268+
[] ::LiteralKind,
269+
[] ::Spacing,
244270
[] ::LexError,
245271
[] ::LineColumn,
246272
[] ::Level,
@@ -269,16 +295,11 @@ macro_rules! each_frontend_method {
269295
$meth!(fn token_stream_is_empty(&self, stream: &Self::TokenStream) -> bool;);
270296
$meth!(fn token_stream_from_str(&self, src: &str)
271297
-> Result<Self::TokenStream, ::LexError>;);
272-
$meth!(fn token_stream_delimited(&self, span: Self::Span,
273-
delimiter: ::Delimiter,
274-
delimed: Self::TokenStream)
275-
-> Self::TokenStream;);
276-
$meth!(fn token_stream_from_token_tree(&self, node: ::TokenNode, span: Self::Span)
298+
$meth!(fn token_stream_from_token_tree(&self, node: Self::TokenNode, span: Self::Span)
277299
-> Self::TokenStream;);
278300
$meth!(fn token_stream_to_token_tree(&self, stream: Self::TokenStream)
279-
-> (Self::Span,
280-
Result<(::TokenNode, Option<Self::TokenStream>),
281-
(::Delimiter, Self::TokenStream)>););
301+
-> ((Self::Span, Self::TokenNode),
302+
Option<Self::TokenStream>););
282303
$meth!(fn token_stream_trees(&self, stream: Self::TokenStream) -> Self::TokenCursor;);
283304

284305
$meth!(fn token_stream_builder_cleanup(&self, _builder: Self::TokenStreamBuilder) -> () {});
@@ -323,6 +344,12 @@ macro_rules! each_frontend_method {
323344
$meth!(fn span_end(&self, span: Self::Span) -> ::LineColumn;);
324345
$meth!(fn span_join(&self, first: Self::Span, second: Self::Span) -> Option<Self::Span>;);
325346
$meth!(fn span_resolved_at(&self, span: Self::Span, at: Self::Span) -> Self::Span;);
347+
348+
$meth!(fn term_debug(&self, term: Self::Term, f: &mut fmt::Formatter) -> fmt::Result {
349+
fmt::Debug::fmt(&term, f)
350+
});
351+
$meth!(fn term_intern(&self, string: &str) -> Self::Term;);
352+
$meth!(fn term_as_str(&self, term: Self::Term) -> ThreadRef<str>;);
326353
}
327354
}
328355

@@ -337,9 +364,49 @@ pub trait FrontendInterface {
337364
type Diagnostic: 'static;
338365
/// NB. has to be the same size as u32.
339366
type Span: 'static + Copy + Eq + fmt::Debug;
367+
/// NB. has to be the same size as u32.
368+
type Term: 'static + Copy + Eq + fmt::Debug;
369+
/// Only needed for object safety, should always be `TokenNode<Self>`.
370+
type TokenNode;
340371
each_frontend_method!(define_frontend_trait_method);
341372
}
342373

374+
macro_rules! frontend_wrapper {
375+
(enum $name:ident<$F:ident> { $($variant:ident($($field:ident: $field_ty:ty),*)),* }) => {
376+
#[repr(C)]
377+
pub enum $name<$F: FrontendInterface> {
378+
$($variant($($field_ty),*)),*
379+
}
380+
381+
impl<F: FrontendInterface> FromConcrete<$name<F>, $name<Frontend>> for Storage<F> {
382+
fn from_concrete(&self, x: $name<F>) -> $name<Frontend> {
383+
match x {
384+
$($name::$variant($($field),*) => {
385+
$name::$variant($(self.from_concrete($field)),*)
386+
}),*
387+
}
388+
}
389+
}
390+
391+
impl<F: FrontendInterface> ToConcrete<$name<Frontend>, $name<F>> for Storage<F> {
392+
fn to_concrete(&self, x: $name<Frontend>) -> $name<F> {
393+
match x {
394+
$($name::$variant($($field),*) => {
395+
$name::$variant($(self.to_concrete($field)),*)
396+
}),*
397+
}
398+
}
399+
}
400+
}
401+
}
402+
403+
frontend_wrapper!(enum TokenNode<F> {
404+
Group(delim: ::Delimiter, delimed: F::TokenStream),
405+
Term(term: F::Term),
406+
Op(op: char, spacing: ::Spacing),
407+
Literal(kind: ::LiteralKind, contents: F::Term, suffix: Option<F::Term>)
408+
});
409+
343410
macro_rules! define_boxed {
344411
($($name:ident { cleanup: $cleanup:ident }),*) => {
345412
$(
@@ -353,28 +420,28 @@ macro_rules! define_boxed {
353420
Frontend.$cleanup($name(boxed))
354421
}
355422
}
356-
impl<S, T: 'static> FromConcrete<T, $name> for storage::Storage<S>
423+
impl<S, T: 'static> FromConcrete<T, $name> for Storage<S>
357424
where $name: storage::Concrete<S, Concrete = T>
358425
{
359426
fn from_concrete(&self, x: T) -> $name {
360427
$name(self.from_concrete(Box::new(x)))
361428
}
362429
}
363-
impl<S, T: 'static> ToConcrete<$name, T> for storage::Storage<S>
430+
impl<S, T: 'static> ToConcrete<$name, T> for Storage<S>
364431
where $name: storage::Concrete<S, Concrete = T>
365432
{
366433
fn to_concrete(&self, x: $name) -> T {
367434
*self.to_concrete(x.0)
368435
}
369436
}
370-
impl<'a, S, T: 'static> ToConcrete<&'a $name, &'a T> for storage::Storage<S>
437+
impl<'a, S, T: 'static> ToConcrete<&'a $name, &'a T> for Storage<S>
371438
where $name: storage::Concrete<S, Concrete = T>
372439
{
373440
fn to_concrete(&self, x: &'a $name) -> &'a T {
374441
self.to_concrete(&x.0)
375442
}
376443
}
377-
impl<'a, S, T: 'static> ToConcrete<&'a mut $name, &'a mut T> for storage::Storage<S>
444+
impl<'a, S, T: 'static> ToConcrete<&'a mut $name, &'a mut T> for Storage<S>
378445
where $name: storage::Concrete<S, Concrete = T>
379446
{
380447
fn to_concrete(&self, x: &'a mut $name) -> &'a mut T {
@@ -442,14 +509,14 @@ macro_rules! define_inline {
442509
impl<F: FrontendInterface> storage::Concrete<F> for $name {
443510
type Concrete = F::$name;
444511
}
445-
impl<S, T: Copy + 'static> FromConcrete<T, $name> for storage::Storage<S>
512+
impl<S, T: Copy + 'static> FromConcrete<T, $name> for Storage<S>
446513
where $name: storage::Concrete<S, Concrete = T>
447514
{
448515
fn from_concrete(&self, x: T) -> $name {
449516
$name(self.from_concrete(x))
450517
}
451518
}
452-
impl<S, T: Copy + 'static> ToConcrete<$name, T> for storage::Storage<S>
519+
impl<S, T: Copy + 'static> ToConcrete<$name, T> for Storage<S>
453520
where $name: storage::Concrete<S, Concrete = T>
454521
{
455522
fn to_concrete(&self, x: $name) -> T {
@@ -460,14 +527,20 @@ macro_rules! define_inline {
460527
}
461528
}
462529

463-
define_inline!(Span);
530+
define_inline!(Span, Term);
464531

465532
impl fmt::Debug for Span {
466533
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
467534
Frontend.span_debug(*self, f)
468535
}
469536
}
470537

538+
impl fmt::Debug for Term {
539+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
540+
Frontend.term_debug(*self, f)
541+
}
542+
}
543+
471544
pub(crate) struct Frontend;
472545

473546
macro_rules! define_frontend_current_method {
@@ -485,6 +558,8 @@ impl FrontendInterface for Frontend {
485558
type SourceFile = SourceFile;
486559
type Diagnostic = Diagnostic;
487560
type Span = Span;
561+
type Term = Term;
562+
type TokenNode = TokenNode<Frontend>;
488563
each_frontend_method!(define_frontend_current_method);
489564
}
490565

@@ -496,6 +571,8 @@ type CurrentFrontend<'a> = FrontendInterface<
496571
SourceFile = SourceFile,
497572
Diagnostic = Diagnostic,
498573
Span = Span,
574+
Term = Term,
575+
TokenNode = TokenNode<Frontend>,
499576
> + 'a;
500577

501578
// Emulate scoped_thread_local!() here essentially
@@ -537,11 +614,11 @@ fn set_current_frontend<F, R>(frontend: &CurrentFrontend, f: F) -> R
537614
fn erase_concrete_frontend<F, G, R>(ng: extern "C" fn() -> generation::Generation,
538615
frontend: F,
539616
f: G) -> R
540-
where F: FrontendInterface,
541-
G: FnOnce(&CurrentFrontend, &storage::Storage<F>) -> R
617+
where F: FrontendInterface<TokenNode = TokenNode<F>>,
618+
G: FnOnce(&CurrentFrontend, &Storage<F>) -> R
542619
{
543-
struct EraseConcrete<F: FrontendInterface> {
544-
storage: storage::Storage<F>,
620+
struct EraseConcrete<F: FrontendInterface<TokenNode = TokenNode<F>>> {
621+
storage: Storage<F>,
545622
concrete: F
546623
}
547624

@@ -554,18 +631,20 @@ fn erase_concrete_frontend<F, G, R>(ng: extern "C" fn() -> generation::Generatio
554631
}
555632
}
556633
}
557-
impl<F: FrontendInterface> FrontendInterface for EraseConcrete<F> {
634+
impl<F: FrontendInterface<TokenNode = TokenNode<F>>> FrontendInterface for EraseConcrete<F> {
558635
type TokenStream = TokenStream;
559636
type TokenStreamBuilder = TokenStreamBuilder;
560637
type TokenCursor = TokenCursor;
561638
type SourceFile = SourceFile;
562639
type Diagnostic = Diagnostic;
563640
type Span = Span;
641+
type Term = Term;
642+
type TokenNode = TokenNode<Frontend>;
564643
each_frontend_method!(define_frontend_erase_concrete_method);
565644
}
566645

567646
let frontend = EraseConcrete {
568-
storage: storage::Storage::new(ng),
647+
storage: Storage::new(ng),
569648
concrete: frontend
570649
};
571650
f(&frontend, &frontend.storage)
@@ -607,7 +686,7 @@ impl Expand1 {
607686
}
608687

609688
pub fn run<F>(&self, frontend: F, input: F::TokenStream) -> F::TokenStream
610-
where F: FrontendInterface
689+
where F: FrontendInterface<TokenNode = TokenNode<F>>
611690
{
612691
erase_concrete_frontend(self.next_generation, frontend, |frontend, storage| {
613692
let input = storage.from_concrete(input);
@@ -657,7 +736,7 @@ impl Expand2 {
657736

658737
pub fn run<F>(&self, frontend: F, input: F::TokenStream, input2: F::TokenStream)
659738
-> F::TokenStream
660-
where F: FrontendInterface
739+
where F: FrontendInterface<TokenNode = TokenNode<F>>
661740
{
662741
erase_concrete_frontend(self.next_generation, frontend, |frontend, storage| {
663742
let input = storage.from_concrete(input);

src/libproc_macro/lib.rs

+28-18
Original file line numberDiff line numberDiff line change
@@ -121,12 +121,16 @@ pub fn quote_token_stream(stream: TokenStream) -> TokenStream {
121121
#[unstable(feature = "proc_macro", issue = "38356")]
122122
impl From<TokenTree> for TokenStream {
123123
fn from(tree: TokenTree) -> TokenStream {
124-
TokenStream(match tree.kind {
125-
TokenNode::Group(delimiter, tokens) => {
126-
Frontend.token_stream_delimited(tree.span.0, delimiter, tokens.0)
124+
TokenStream(Frontend.token_stream_from_token_tree(match tree.kind {
125+
TokenNode::Group(delim, delimed) => {
126+
bridge::TokenNode::Group(delim, delimed.0)
127127
}
128-
_ => Frontend.token_stream_from_token_tree(tree.kind, tree.span.0)
129-
})
128+
TokenNode::Term(term) => bridge::TokenNode::Term(term.0),
129+
TokenNode::Op(c, s) => bridge::TokenNode::Op(c, s),
130+
TokenNode::Literal(Literal { kind, contents, suffix }) => {
131+
bridge::TokenNode::Literal(kind, contents.0, suffix.map(|s| s.0))
132+
}
133+
}, tree.span.0))
130134
}
131135
}
132136

@@ -393,19 +397,19 @@ pub enum Delimiter {
393397
/// An interned string.
394398
#[derive(Copy, Clone, Debug)]
395399
#[unstable(feature = "proc_macro", issue = "38356")]
396-
pub struct Term(::rustc::Symbol);
400+
pub struct Term(bridge::Term);
397401

398402
impl Term {
399403
/// Intern a string into a `Term`.
400404
#[unstable(feature = "proc_macro", issue = "38356")]
401405
pub fn intern(string: &str) -> Term {
402-
Term(::rustc::Symbol::intern(string))
406+
Term(Frontend.term_intern(string))
403407
}
404408

405409
/// Get a reference to the interned string.
406410
#[unstable(feature = "proc_macro", issue = "38356")]
407411
pub fn as_str(&self) -> &str {
408-
unsafe { &*(&*self.0.as_str() as *const str) }
412+
unsafe { &*(&*Frontend.term_as_str(self.0) as *const str) }
409413
}
410414
}
411415

@@ -597,18 +601,24 @@ impl Iterator for TokenTreeIter {
597601
let next = self.next.take().or_else(|| {
598602
Frontend.token_cursor_next(&mut self.cursor)
599603
})?;
600-
let (span, kind) = match Frontend.token_stream_to_token_tree(next) {
601-
(span, Ok((kind, next))) => {
602-
self.next = next;
603-
(span, kind)
604-
}
605-
(span, Err((delimiter, delimed))) => {
606-
(span, TokenNode::Group(delimiter, TokenStream(delimed)))
607-
}
608-
};
604+
let ((span, kind), next) = Frontend.token_stream_to_token_tree(next);
605+
self.next = next;
609606
Some(TokenTree {
610607
span: Span(span),
611-
kind
608+
kind: match kind {
609+
bridge::TokenNode::Group(delim, delimed) => {
610+
TokenNode::Group(delim, TokenStream(delimed))
611+
}
612+
bridge::TokenNode::Term(term) => TokenNode::Term(Term(term)),
613+
bridge::TokenNode::Op(c, s) => TokenNode::Op(c, s),
614+
bridge::TokenNode::Literal(kind, contents, suffix) => {
615+
TokenNode::Literal(Literal {
616+
kind,
617+
contents: Term(contents),
618+
suffix: suffix.map(Term)
619+
})
620+
}
621+
}
612622
})
613623
}
614624
}

0 commit comments

Comments
 (0)