2121
2222use std:: cell:: Cell ;
2323use std:: fmt;
24+ use std:: ops:: Deref ;
2425use std:: path:: PathBuf ;
2526use std:: ptr:: NonNull ;
2627
27- use self :: storage:: { FromConcrete , ToConcrete } ;
28+ use self :: storage:: { FromConcrete , ToConcrete , Storage } ;
2829
2930mod 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+
236259storage_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+
343410macro_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
465532impl 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+
471544pub ( crate ) struct Frontend ;
472545
473546macro_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
537614fn 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) ;
0 commit comments