@@ -25,7 +25,6 @@ source code snippets, etc.
2525
2626use serialize:: { Encodable , Decodable , Encoder , Decoder } ;
2727use std:: cell:: RefCell ;
28- use std:: gc:: Gc ;
2928use std:: rc:: Rc ;
3029
3130pub trait Pos {
@@ -93,10 +92,10 @@ pub struct Span {
9392 pub hi : BytePos ,
9493 /// Information about where the macro came from, if this piece of
9594 /// code was created by a macro expansion.
96- pub expn_info : Option < Gc < ExpnInfo > >
95+ pub expn_id : ExpnId
9796}
9897
99- pub static DUMMY_SP : Span = Span { lo : BytePos ( 0 ) , hi : BytePos ( 0 ) , expn_info : None } ;
98+ pub static DUMMY_SP : Span = Span { lo : BytePos ( 0 ) , hi : BytePos ( 0 ) , expn_id : NO_EXPANSION } ;
10099
101100#[ deriving( Clone , PartialEq , Eq , Encodable , Decodable , Hash , Show ) ]
102101pub struct Spanned < T > {
@@ -140,17 +139,19 @@ pub fn dummy_spanned<T>(t: T) -> Spanned<T> {
140139
141140/* assuming that we're not in macro expansion */
142141pub fn mk_sp ( lo : BytePos , hi : BytePos ) -> Span {
143- Span { lo : lo, hi : hi, expn_info : None }
142+ Span { lo : lo, hi : hi, expn_id : NO_EXPANSION }
144143}
145144
146145/// Return the span itself if it doesn't come from a macro expansion,
147146/// otherwise return the call site span up to the `enclosing_sp` by
148147/// following the `expn_info` chain.
149- pub fn original_sp ( sp : Span , enclosing_sp : Span ) -> Span {
150- match ( sp. expn_info , enclosing_sp. expn_info ) {
148+ pub fn original_sp ( cm : & CodeMap , sp : Span , enclosing_sp : Span ) -> Span {
149+ let call_site1 = cm. with_expn_info ( sp. expn_id , |ei| ei. map ( |ei| ei. call_site ) ) ;
150+ let call_site2 = cm. with_expn_info ( enclosing_sp. expn_id , |ei| ei. map ( |ei| ei. call_site ) ) ;
151+ match ( call_site1, call_site2) {
151152 ( None , _) => sp,
152- ( Some ( expn1 ) , Some ( expn2 ) ) if expn1 . call_site == expn2 . call_site => sp,
153- ( Some ( expn1 ) , _) => original_sp ( expn1 . call_site , enclosing_sp) ,
153+ ( Some ( call_site1 ) , Some ( call_site2 ) ) if call_site1 == call_site2 => sp,
154+ ( Some ( call_site1 ) , _) => original_sp ( cm , call_site1 , enclosing_sp) ,
154155 }
155156}
156157
@@ -222,6 +223,11 @@ pub struct ExpnInfo {
222223 pub callee : NameAndSpan
223224}
224225
226+ #[ deriving( PartialEq , Eq , Clone , Show , Hash ) ]
227+ pub struct ExpnId ( u32 ) ;
228+
229+ pub static NO_EXPANSION : ExpnId = ExpnId ( -1 ) ;
230+
225231pub type FileName = String ;
226232
227233pub struct FileLines {
@@ -299,13 +305,15 @@ impl FileMap {
299305}
300306
301307pub struct CodeMap {
302- pub files : RefCell < Vec < Rc < FileMap > > >
308+ pub files : RefCell < Vec < Rc < FileMap > > > ,
309+ expansions : RefCell < Vec < ExpnInfo > >
303310}
304311
305312impl CodeMap {
306313 pub fn new ( ) -> CodeMap {
307314 CodeMap {
308315 files : RefCell :: new ( Vec :: new ( ) ) ,
316+ expansions : RefCell :: new ( Vec :: new ( ) ) ,
309317 }
310318 }
311319
@@ -527,6 +535,19 @@ impl CodeMap {
527535 col : chpos - linechpos
528536 }
529537 }
538+
539+ pub fn record_expansion ( & self , expn_info : ExpnInfo ) -> ExpnId {
540+ let mut expansions = self . expansions . borrow_mut ( ) ;
541+ expansions. push ( expn_info) ;
542+ ExpnId ( expansions. len ( ) . to_u32 ( ) . expect ( "too many ExpnInfo's!" ) - 1 )
543+ }
544+
545+ pub fn with_expn_info < T > ( & self , id : ExpnId , f: |Option < & ExpnInfo > | -> T ) -> T {
546+ match id {
547+ NO_EXPANSION => f ( None ) ,
548+ ExpnId ( i) => f ( Some ( & ( * self . expansions . borrow ( ) ) [ i as uint ] ) )
549+ }
550+ }
530551}
531552
532553#[ cfg( test) ]
@@ -665,7 +686,7 @@ mod test {
665686 fn t7 ( ) {
666687 // Test span_to_lines for a span ending at the end of filemap
667688 let cm = init_code_map ( ) ;
668- let span = Span { lo : BytePos ( 12 ) , hi : BytePos ( 23 ) , expn_info : None } ;
689+ let span = Span { lo : BytePos ( 12 ) , hi : BytePos ( 23 ) , expn_id : NO_EXPANSION } ;
669690 let file_lines = cm. span_to_lines ( span) ;
670691
671692 assert_eq ! ( file_lines. file. name, "blork.rs" . to_string( ) ) ;
@@ -677,7 +698,7 @@ mod test {
677698 fn t8 ( ) {
678699 // Test span_to_snippet for a span ending at the end of filemap
679700 let cm = init_code_map ( ) ;
680- let span = Span { lo : BytePos ( 12 ) , hi : BytePos ( 23 ) , expn_info : None } ;
701+ let span = Span { lo : BytePos ( 12 ) , hi : BytePos ( 23 ) , expn_id : NO_EXPANSION } ;
681702 let snippet = cm. span_to_snippet ( span) ;
682703
683704 assert_eq ! ( snippet, Some ( "second line" . to_string( ) ) ) ;
@@ -687,7 +708,7 @@ mod test {
687708 fn t9 ( ) {
688709 // Test span_to_str for a span ending at the end of filemap
689710 let cm = init_code_map ( ) ;
690- let span = Span { lo : BytePos ( 12 ) , hi : BytePos ( 23 ) , expn_info : None } ;
711+ let span = Span { lo : BytePos ( 12 ) , hi : BytePos ( 23 ) , expn_id : NO_EXPANSION } ;
691712 let sstr = cm. span_to_string ( span) ;
692713
693714 assert_eq ! ( sstr, "blork.rs:2:1: 2:12" . to_string( ) ) ;
0 commit comments