@@ -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}
@@ -184,8 +177,6 @@ impl iter::FromIterator<TokenStream> for TokenStream {
184177#[ unstable( feature = "proc_macro" , issue = "38356" ) ]
185178pub mod token_stream {
186179 use syntax:: tokenstream;
187- use syntax_pos:: DUMMY_SP ;
188-
189180 use { TokenTree , TokenStream , Delimiter } ;
190181
191182 /// An iterator over `TokenStream`'s `TokenTree`s.
@@ -214,7 +205,7 @@ pub mod token_stream {
214205 // need to flattened during iteration over stream's token trees.
215206 // Eventually this needs to be removed in favor of keeping original token trees
216207 // and not doing the roundtrip through AST.
217- if tree. span ( ) . 0 == DUMMY_SP {
208+ if tree. span ( ) . 0 . is_dummy ( ) {
218209 if let TokenTree :: Group ( ref group) = tree {
219210 if group. delimiter ( ) == Delimiter :: None {
220211 self . cursor . insert ( group. stream . clone ( ) . 0 ) ;
@@ -284,10 +275,7 @@ impl Span {
284275 /// A span that resolves at the macro definition site.
285276 #[ unstable( feature = "proc_macro" , issue = "38356" ) ]
286277 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- } )
278+ :: __internal:: with_sess ( |_, data| data. def_site )
291279 }
292280
293281 /// The span of the invocation of the current procedural macro.
@@ -296,7 +284,7 @@ impl Span {
296284 /// at the macro call site will be able to refer to them as well.
297285 #[ unstable( feature = "proc_macro" , issue = "38356" ) ]
298286 pub fn call_site ( ) -> Span {
299- :: __internal:: with_sess ( |( _, mark ) | Span ( mark . expn_info ( ) . unwrap ( ) . call_site ) )
287+ :: __internal:: with_sess ( |_, data| data . call_site )
300288 }
301289
302290 /// The original source file into which this span points.
@@ -1243,7 +1231,7 @@ impl TokenTree {
12431231 }
12441232
12451233 Interpolated ( _) => {
1246- __internal:: with_sess ( |( sess, _) | {
1234+ __internal:: with_sess ( |sess, _| {
12471235 let tts = token. interpolated_to_tokenstream ( sess, span) ;
12481236 tt ! ( Group :: new( Delimiter :: None , TokenStream ( tts) ) )
12491237 } )
@@ -1354,20 +1342,21 @@ pub mod __internal {
13541342 pub use quote:: { LiteralKind , SpannedSymbol , Quoter , unquote} ;
13551343
13561344 use std:: cell:: Cell ;
1345+ use std:: ptr;
13571346
13581347 use syntax:: ast;
13591348 use syntax:: ext:: base:: ExtCtxt ;
1360- use syntax:: ext:: hygiene:: Mark ;
13611349 use syntax:: ptr:: P ;
13621350 use syntax:: parse:: { self , ParseSess } ;
13631351 use syntax:: parse:: token:: { self , Token } ;
13641352 use syntax:: tokenstream;
13651353 use syntax_pos:: { BytePos , Loc , DUMMY_SP } ;
1354+ use syntax_pos:: hygiene:: { Mark , SyntaxContext , Transparency } ;
13661355
1367- use super :: { TokenStream , LexError } ;
1356+ use super :: { TokenStream , LexError , Span } ;
13681357
13691358 pub fn lookup_char_pos ( pos : BytePos ) -> Loc {
1370- with_sess ( |( sess, _) | sess. codemap ( ) . lookup_char_pos ( pos) )
1359+ with_sess ( |sess, _| sess. codemap ( ) . lookup_char_pos ( pos) )
13711360 }
13721361
13731362 pub fn new_token_stream ( item : P < ast:: Item > ) -> TokenStream {
@@ -1380,7 +1369,7 @@ pub mod __internal {
13801369 }
13811370
13821371 pub fn token_stream_parse_items ( stream : TokenStream ) -> Result < Vec < P < ast:: Item > > , LexError > {
1383- with_sess ( move |( sess, _) | {
1372+ with_sess ( move |sess, _| {
13841373 let mut parser = parse:: stream_to_parser ( sess, stream. 0 ) ;
13851374 let mut items = Vec :: new ( ) ;
13861375
@@ -1411,16 +1400,30 @@ pub mod __internal {
14111400 expand : fn ( TokenStream ) -> TokenStream ) ;
14121401 }
14131402
1403+ #[ derive( Clone , Copy ) ]
1404+ pub struct ProcMacroData {
1405+ pub def_site : Span ,
1406+ pub call_site : Span ,
1407+ }
1408+
1409+ #[ derive( Clone , Copy ) ]
1410+ struct ProcMacroSess {
1411+ parse_sess : * const ParseSess ,
1412+ data : ProcMacroData ,
1413+ }
1414+
14141415 // Emulate scoped_thread_local!() here essentially
14151416 thread_local ! {
1416- static CURRENT_SESS : Cell <( * const ParseSess , Mark ) > =
1417- Cell :: new( ( 0 as * const _, Mark :: root( ) ) ) ;
1417+ static CURRENT_SESS : Cell <ProcMacroSess > = Cell :: new( ProcMacroSess {
1418+ parse_sess: ptr:: null( ) ,
1419+ data: ProcMacroData { def_site: Span ( DUMMY_SP ) , call_site: Span ( DUMMY_SP ) } ,
1420+ } ) ;
14181421 }
14191422
14201423 pub fn set_sess < F , R > ( cx : & ExtCtxt , f : F ) -> R
14211424 where F : FnOnce ( ) -> R
14221425 {
1423- struct Reset { prev : ( * const ParseSess , Mark ) }
1426+ struct Reset { prev : ProcMacroSess }
14241427
14251428 impl Drop for Reset {
14261429 fn drop ( & mut self ) {
@@ -1430,24 +1433,42 @@ pub mod __internal {
14301433
14311434 CURRENT_SESS . with ( |p| {
14321435 let _reset = Reset { prev : p. get ( ) } ;
1433- p. set ( ( cx. parse_sess , cx. current_expansion . mark ) ) ;
1436+
1437+ // No way to determine def location for a proc macro right now, so use call location.
1438+ let location = cx. current_expansion . mark . expn_info ( ) . unwrap ( ) . call_site ;
1439+ // Opaque mark was already created by expansion, now create its transparent twin.
1440+ // We can't use the call-site span literally here, even if it appears to provide
1441+ // correct name resolution, because it has all the `ExpnInfo` wrong, so the edition
1442+ // checks, lint macro checks, macro backtraces will all break.
1443+ let opaque_mark = cx. current_expansion . mark ;
1444+ let transparent_mark = Mark :: fresh_cloned ( opaque_mark) ;
1445+ transparent_mark. set_transparency ( Transparency :: Transparent ) ;
1446+
1447+ let to_span = |mark| Span ( location. with_ctxt ( SyntaxContext :: empty ( ) . apply_mark ( mark) ) ) ;
1448+ p. set ( ProcMacroSess {
1449+ parse_sess : cx. parse_sess ,
1450+ data : ProcMacroData {
1451+ def_site : to_span ( opaque_mark) ,
1452+ call_site : to_span ( transparent_mark) ,
1453+ } ,
1454+ } ) ;
14341455 f ( )
14351456 } )
14361457 }
14371458
14381459 pub fn in_sess ( ) -> bool
14391460 {
1440- let p = CURRENT_SESS . with ( |p| p. get ( ) ) ;
1441- !p. 0 . is_null ( )
1461+ !CURRENT_SESS . with ( |sess| sess. get ( ) ) . parse_sess . is_null ( )
14421462 }
14431463
14441464 pub fn with_sess < F , R > ( f : F ) -> R
1445- where F : FnOnce ( ( & ParseSess , Mark ) ) -> R
1465+ where F : FnOnce ( & ParseSess , & ProcMacroData ) -> R
14461466 {
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 ) } )
1467+ let sess = CURRENT_SESS . with ( |sess| sess. get ( ) ) ;
1468+ if sess. parse_sess . is_null ( ) {
1469+ panic ! ( "procedural macro API is used outside of a procedural macro" ) ;
1470+ }
1471+ f ( unsafe { & * sess. parse_sess } , & sess. data )
14511472 }
14521473}
14531474
0 commit comments