@@ -58,8 +58,7 @@ use syntax::parse::{self, token};
5858use syntax:: symbol:: { keywords, Symbol } ;
5959use syntax:: tokenstream;
6060use syntax:: parse:: lexer:: { self , comments} ;
61- use syntax_pos:: { FileMap , Pos , SyntaxContext , FileName } ;
62- use syntax_pos:: hygiene:: Mark ;
61+ use syntax_pos:: { FileMap , Pos , FileName } ;
6362
6463/// The main type provided by this crate, representing an abstract stream of
6564/// tokens, or, more specifically, a sequence of token trees.
@@ -109,6 +108,7 @@ impl TokenStream {
109108/// Attempts to break the string into tokens and parse those tokens into a token stream.
110109/// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
111110/// or characters not existing in the language.
111+ /// All tokens in the parsed stream get `Span::call_site()` spans.
112112///
113113/// NOTE: Some errors may cause panics instead of returning `LexError`. We reserve the right to
114114/// change these errors into `LexError`s later.
@@ -117,17 +117,10 @@ impl FromStr for TokenStream {
117117 type Err = LexError ;
118118
119119 fn from_str ( src : & str ) -> Result < TokenStream , LexError > {
120- __internal:: with_sess ( |( sess, mark) | {
121- let src = src. to_string ( ) ;
122- let name = FileName :: ProcMacroSourceCode ;
123- let expn_info = mark. expn_info ( ) . unwrap ( ) ;
124- let call_site = expn_info. call_site ;
125- // notify the expansion info that it is unhygienic
126- let mark = Mark :: fresh ( mark) ;
127- mark. set_expn_info ( expn_info) ;
128- let span = call_site. with_ctxt ( SyntaxContext :: empty ( ) . apply_mark ( mark) ) ;
129- let stream = parse:: parse_stream_from_source_str ( name, src, sess, Some ( span) ) ;
130- Ok ( __internal:: token_stream_wrap ( stream) )
120+ __internal:: with_sess ( |sess, data| {
121+ Ok ( __internal:: token_stream_wrap ( parse:: parse_stream_from_source_str (
122+ FileName :: ProcMacroSourceCode , src. to_string ( ) , sess, Some ( data. call_site . 0 )
123+ ) ) )
131124 } )
132125 }
133126}
@@ -284,10 +277,7 @@ impl Span {
284277 /// A span that resolves at the macro definition site.
285278 #[ unstable( feature = "proc_macro" , issue = "38356" ) ]
286279 pub fn def_site ( ) -> Span {
287- :: __internal:: with_sess ( |( _, mark) | {
288- let call_site = mark. expn_info ( ) . unwrap ( ) . call_site ;
289- Span ( call_site. with_ctxt ( SyntaxContext :: empty ( ) . apply_mark ( mark) ) )
290- } )
280+ :: __internal:: with_sess ( |_, data| data. def_site )
291281 }
292282
293283 /// The span of the invocation of the current procedural macro.
@@ -296,7 +286,7 @@ impl Span {
296286 /// at the macro call site will be able to refer to them as well.
297287 #[ unstable( feature = "proc_macro" , issue = "38356" ) ]
298288 pub fn call_site ( ) -> Span {
299- :: __internal:: with_sess ( |( _, mark ) | Span ( mark . expn_info ( ) . unwrap ( ) . call_site ) )
289+ :: __internal:: with_sess ( |_, data| data . call_site )
300290 }
301291
302292 /// The original source file into which this span points.
@@ -1243,7 +1233,7 @@ impl TokenTree {
12431233 }
12441234
12451235 Interpolated ( _) => {
1246- __internal:: with_sess ( |( sess, _) | {
1236+ __internal:: with_sess ( |sess, _| {
12471237 let tts = token. interpolated_to_tokenstream ( sess, span) ;
12481238 tt ! ( Group :: new( Delimiter :: None , TokenStream ( tts) ) )
12491239 } )
@@ -1354,20 +1344,21 @@ pub mod __internal {
13541344 pub use quote:: { LiteralKind , SpannedSymbol , Quoter , unquote} ;
13551345
13561346 use std:: cell:: Cell ;
1347+ use std:: ptr;
13571348
13581349 use syntax:: ast;
13591350 use syntax:: ext:: base:: ExtCtxt ;
1360- use syntax:: ext:: hygiene:: Mark ;
13611351 use syntax:: ptr:: P ;
13621352 use syntax:: parse:: { self , ParseSess } ;
13631353 use syntax:: parse:: token:: { self , Token } ;
13641354 use syntax:: tokenstream;
13651355 use syntax_pos:: { BytePos , Loc , DUMMY_SP } ;
1356+ use syntax_pos:: hygiene:: { Mark , SyntaxContext , Transparency } ;
13661357
1367- use super :: { TokenStream , LexError } ;
1358+ use super :: { TokenStream , LexError , Span } ;
13681359
13691360 pub fn lookup_char_pos ( pos : BytePos ) -> Loc {
1370- with_sess ( |( sess, _) | sess. codemap ( ) . lookup_char_pos ( pos) )
1361+ with_sess ( |sess, _| sess. codemap ( ) . lookup_char_pos ( pos) )
13711362 }
13721363
13731364 pub fn new_token_stream ( item : P < ast:: Item > ) -> TokenStream {
@@ -1380,7 +1371,7 @@ pub mod __internal {
13801371 }
13811372
13821373 pub fn token_stream_parse_items ( stream : TokenStream ) -> Result < Vec < P < ast:: Item > > , LexError > {
1383- with_sess ( move |( sess, _) | {
1374+ with_sess ( move |sess, _| {
13841375 let mut parser = parse:: stream_to_parser ( sess, stream. 0 ) ;
13851376 let mut items = Vec :: new ( ) ;
13861377
@@ -1411,16 +1402,30 @@ pub mod __internal {
14111402 expand : fn ( TokenStream ) -> TokenStream ) ;
14121403 }
14131404
1405+ #[ derive( Clone , Copy ) ]
1406+ pub struct ProcMacroData {
1407+ pub def_site : Span ,
1408+ pub call_site : Span ,
1409+ }
1410+
1411+ #[ derive( Clone , Copy ) ]
1412+ struct ProcMacroSess {
1413+ parse_sess : * const ParseSess ,
1414+ data : ProcMacroData ,
1415+ }
1416+
14141417 // Emulate scoped_thread_local!() here essentially
14151418 thread_local ! {
1416- static CURRENT_SESS : Cell <( * const ParseSess , Mark ) > =
1417- Cell :: new( ( 0 as * const _, Mark :: root( ) ) ) ;
1419+ static CURRENT_SESS : Cell <ProcMacroSess > = Cell :: new( ProcMacroSess {
1420+ parse_sess: ptr:: null( ) ,
1421+ data: ProcMacroData { def_site: Span ( DUMMY_SP ) , call_site: Span ( DUMMY_SP ) } ,
1422+ } ) ;
14181423 }
14191424
14201425 pub fn set_sess < F , R > ( cx : & ExtCtxt , f : F ) -> R
14211426 where F : FnOnce ( ) -> R
14221427 {
1423- struct Reset { prev : ( * const ParseSess , Mark ) }
1428+ struct Reset { prev : ProcMacroSess }
14241429
14251430 impl Drop for Reset {
14261431 fn drop ( & mut self ) {
@@ -1430,24 +1435,39 @@ pub mod __internal {
14301435
14311436 CURRENT_SESS . with ( |p| {
14321437 let _reset = Reset { prev : p. get ( ) } ;
1433- p. set ( ( cx. parse_sess , cx. current_expansion . mark ) ) ;
1438+
1439+ // No way to determine def location for a proc macro rigth now, so use call location.
1440+ let location = cx. current_expansion . mark . expn_info ( ) . unwrap ( ) . call_site ;
1441+ // Opaque mark was already created by expansion, now create its transparent twin.
1442+ let opaque_mark = cx. current_expansion . mark ;
1443+ let transparent_mark = Mark :: fresh_cloned ( opaque_mark) ;
1444+ transparent_mark. set_transparency ( Transparency :: Transparent ) ;
1445+
1446+ let to_span = |mark| Span ( location. with_ctxt ( SyntaxContext :: empty ( ) . apply_mark ( mark) ) ) ;
1447+ p. set ( ProcMacroSess {
1448+ parse_sess : cx. parse_sess ,
1449+ data : ProcMacroData {
1450+ def_site : to_span ( opaque_mark) ,
1451+ call_site : to_span ( transparent_mark) ,
1452+ } ,
1453+ } ) ;
14341454 f ( )
14351455 } )
14361456 }
14371457
14381458 pub fn in_sess ( ) -> bool
14391459 {
1440- let p = CURRENT_SESS . with ( |p| p. get ( ) ) ;
1441- !p. 0 . is_null ( )
1460+ !CURRENT_SESS . with ( |sess| sess. get ( ) ) . parse_sess . is_null ( )
14421461 }
14431462
14441463 pub fn with_sess < F , R > ( f : F ) -> R
1445- where F : FnOnce ( ( & ParseSess , Mark ) ) -> R
1464+ where F : FnOnce ( & ParseSess , & ProcMacroData ) -> R
14461465 {
1447- let p = CURRENT_SESS . with ( |p| p. get ( ) ) ;
1448- assert ! ( !p. 0 . is_null( ) , "proc_macro::__internal::with_sess() called \
1449- before set_parse_sess()!") ;
1450- f ( unsafe { ( & * p. 0 , p. 1 ) } )
1466+ let sess = CURRENT_SESS . with ( |sess| sess. get ( ) ) ;
1467+ if sess. parse_sess . is_null ( ) {
1468+ panic ! ( "procedural macro API is used outside of a procedural macro" ) ;
1469+ }
1470+ f ( unsafe { & * sess. parse_sess } , & sess. data )
14511471 }
14521472}
14531473
0 commit comments