2222use std:: cell:: Cell ;
2323use std:: fmt;
2424use std:: ops:: Deref ;
25+ use std:: panic;
2526use std:: path:: PathBuf ;
2627use std:: ptr:: NonNull ;
28+ use std:: thread;
2729
2830use self :: storage:: { FromConcrete , ToConcrete , Storage } ;
2931
@@ -580,8 +582,20 @@ thread_local! {
580582 static CURRENT_FRONTEND : Cell <Option <NonNull <CurrentFrontend <' static >>>> = Cell :: new( None ) ;
581583}
582584
583- pub fn has_current_frontend ( ) -> bool {
584- CURRENT_FRONTEND . with ( |p| p. get ( ) . is_some ( ) )
585+ // Hide the default panic output within `proc_macro` expansions.
586+ // NB. frontends can't do this because they may use a different libstd.
587+ lazy_static ! {
588+ static ref DEFAULT_HOOK : Box <Fn ( & panic:: PanicInfo ) + Sync + Send + ' static > = {
589+ let hook = panic:: take_hook( ) ;
590+ panic:: set_hook( Box :: new( panic_hook) ) ;
591+ hook
592+ } ;
593+ }
594+
595+ fn panic_hook ( info : & panic:: PanicInfo ) {
596+ if CURRENT_FRONTEND . with ( |p| p. get ( ) . is_none ( ) ) {
597+ ( * DEFAULT_HOOK ) ( info)
598+ }
585599}
586600
587601fn with_current_frontend < F , R > ( f : F ) -> R
@@ -604,6 +618,9 @@ fn set_current_frontend<F, R>(frontend: &CurrentFrontend, f: F) -> R
604618 }
605619 }
606620
621+ // Ensure panic output hiding is set up.
622+ :: lazy_static:: initialize ( & DEFAULT_HOOK ) ;
623+
607624 CURRENT_FRONTEND . with ( |p| {
608625 let _reset = Reset { prev : p. get ( ) } ;
609626 p. set ( NonNull :: new ( frontend as * const _ as * mut _ ) ) ;
@@ -657,8 +674,9 @@ fn erase_concrete_frontend<F, G, R>(ng: extern "C" fn() -> generation::Generatio
657674pub struct Expand1 {
658675 next_generation : extern "C" fn ( ) -> generation:: Generation ,
659676 data : * const ( ) ,
677+ // FIXME(eddyb) achieve ABI compatibility for the `thread::Result` type.
660678 run : unsafe extern "C" fn ( * const ( ) , & & CurrentFrontend , TokenStream )
661- -> TokenStream ,
679+ -> thread :: Result < TokenStream > ,
662680}
663681
664682impl !Send for Expand1 { }
@@ -670,12 +688,15 @@ impl Expand1 {
670688 {
671689 unsafe extern "C" fn run < F > ( f : * const ( ) ,
672690 frontend : & & CurrentFrontend ,
673- input : TokenStream ) -> TokenStream
691+ input : TokenStream )
692+ -> thread:: Result < TokenStream >
674693 where F : Fn ( :: TokenStream ) -> :: TokenStream
675694 {
676695 let f = & * ( f as * const F ) ;
677696 set_current_frontend ( * frontend, || {
678- f ( :: TokenStream ( input) ) . 0
697+ panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
698+ f ( :: TokenStream ( input) ) . 0
699+ } ) )
679700 } )
680701 }
681702 Expand1 {
@@ -685,15 +706,16 @@ impl Expand1 {
685706 }
686707 }
687708
688- pub fn run < F > ( & self , frontend : F , input : F :: TokenStream ) -> F :: TokenStream
709+ pub fn run < F > ( & self , frontend : F , input : F :: TokenStream )
710+ -> thread:: Result < F :: TokenStream >
689711 where F : FrontendInterface < TokenNode = TokenNode < F > >
690712 {
691713 erase_concrete_frontend ( self . next_generation , frontend, |frontend, storage| {
692714 let input = storage. from_concrete ( input) ;
693715 let output = unsafe {
694716 ( self . run ) ( self . data , & frontend, input)
695717 } ;
696- storage. to_concrete ( output)
718+ output . map ( |output| storage. to_concrete ( output) )
697719 } )
698720 }
699721}
@@ -705,8 +727,9 @@ impl Expand1 {
705727pub struct Expand2 {
706728 next_generation : extern "C" fn ( ) -> generation:: Generation ,
707729 data : * const ( ) ,
730+ // FIXME(eddyb) achieve ABI compatibility for the `thread::Result` type.
708731 run : unsafe extern "C" fn ( * const ( ) , & & CurrentFrontend , TokenStream , TokenStream )
709- -> TokenStream ,
732+ -> thread :: Result < TokenStream > ,
710733}
711734
712735impl !Send for Expand2 { }
@@ -719,12 +742,15 @@ impl Expand2 {
719742 unsafe extern "C" fn run < F > ( f : * const ( ) ,
720743 frontend : & & CurrentFrontend ,
721744 input : TokenStream ,
722- input2 : TokenStream ) -> TokenStream
745+ input2 : TokenStream )
746+ -> thread:: Result < TokenStream >
723747 where F : Fn ( :: TokenStream , :: TokenStream ) -> :: TokenStream
724748 {
725749 let f = & * ( f as * const F ) ;
726750 set_current_frontend ( * frontend, || {
727- f ( :: TokenStream ( input) , :: TokenStream ( input2) ) . 0
751+ panic:: catch_unwind ( panic:: AssertUnwindSafe ( || {
752+ f ( :: TokenStream ( input) , :: TokenStream ( input2) ) . 0
753+ } ) )
728754 } )
729755 }
730756 Expand2 {
@@ -735,7 +761,7 @@ impl Expand2 {
735761 }
736762
737763 pub fn run < F > ( & self , frontend : F , input : F :: TokenStream , input2 : F :: TokenStream )
738- -> F :: TokenStream
764+ -> thread :: Result < F :: TokenStream >
739765 where F : FrontendInterface < TokenNode = TokenNode < F > >
740766 {
741767 erase_concrete_frontend ( self . next_generation , frontend, |frontend, storage| {
@@ -744,7 +770,7 @@ impl Expand2 {
744770 let output = unsafe {
745771 ( self . run ) ( self . data , & frontend, input, input2)
746772 } ;
747- storage. to_concrete ( output)
773+ output . map ( |output| storage. to_concrete ( output) )
748774 } )
749775 }
750776}
0 commit comments