@@ -58,8 +58,7 @@ use syntax::parse::{self, token};
58
58
use syntax:: symbol:: { keywords, Symbol } ;
59
59
use syntax:: tokenstream;
60
60
use 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 } ;
63
62
64
63
/// The main type provided by this crate, representing an abstract stream of
65
64
/// tokens, or, more specifically, a sequence of token trees.
@@ -109,6 +108,7 @@ impl TokenStream {
109
108
/// Attempts to break the string into tokens and parse those tokens into a token stream.
110
109
/// May fail for a number of reasons, for example, if the string contains unbalanced delimiters
111
110
/// or characters not existing in the language.
111
+ /// All tokens in the parsed stream get `Span::call_site()` spans.
112
112
///
113
113
/// NOTE: Some errors may cause panics instead of returning `LexError`. We reserve the right to
114
114
/// change these errors into `LexError`s later.
@@ -117,17 +117,10 @@ impl FromStr for TokenStream {
117
117
type Err = LexError ;
118
118
119
119
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
+ ) ) )
131
124
} )
132
125
}
133
126
}
@@ -284,10 +277,7 @@ impl Span {
284
277
/// A span that resolves at the macro definition site.
285
278
#[ unstable( feature = "proc_macro" , issue = "38356" ) ]
286
279
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 )
291
281
}
292
282
293
283
/// The span of the invocation of the current procedural macro.
@@ -296,7 +286,7 @@ impl Span {
296
286
/// at the macro call site will be able to refer to them as well.
297
287
#[ unstable( feature = "proc_macro" , issue = "38356" ) ]
298
288
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 )
300
290
}
301
291
302
292
/// The original source file into which this span points.
@@ -1243,7 +1233,7 @@ impl TokenTree {
1243
1233
}
1244
1234
1245
1235
Interpolated ( _) => {
1246
- __internal:: with_sess ( |( sess, _) | {
1236
+ __internal:: with_sess ( |sess, _| {
1247
1237
let tts = token. interpolated_to_tokenstream ( sess, span) ;
1248
1238
tt ! ( Group :: new( Delimiter :: None , TokenStream ( tts) ) )
1249
1239
} )
@@ -1354,20 +1344,21 @@ pub mod __internal {
1354
1344
pub use quote:: { LiteralKind , SpannedSymbol , Quoter , unquote} ;
1355
1345
1356
1346
use std:: cell:: Cell ;
1347
+ use std:: ptr;
1357
1348
1358
1349
use syntax:: ast;
1359
1350
use syntax:: ext:: base:: ExtCtxt ;
1360
- use syntax:: ext:: hygiene:: Mark ;
1361
1351
use syntax:: ptr:: P ;
1362
1352
use syntax:: parse:: { self , ParseSess } ;
1363
1353
use syntax:: parse:: token:: { self , Token } ;
1364
1354
use syntax:: tokenstream;
1365
1355
use syntax_pos:: { BytePos , Loc , DUMMY_SP } ;
1356
+ use syntax_pos:: hygiene:: { Mark , SyntaxContext , Transparency } ;
1366
1357
1367
- use super :: { TokenStream , LexError } ;
1358
+ use super :: { TokenStream , LexError , Span } ;
1368
1359
1369
1360
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) )
1371
1362
}
1372
1363
1373
1364
pub fn new_token_stream ( item : P < ast:: Item > ) -> TokenStream {
@@ -1380,7 +1371,7 @@ pub mod __internal {
1380
1371
}
1381
1372
1382
1373
pub fn token_stream_parse_items ( stream : TokenStream ) -> Result < Vec < P < ast:: Item > > , LexError > {
1383
- with_sess ( move |( sess, _) | {
1374
+ with_sess ( move |sess, _| {
1384
1375
let mut parser = parse:: stream_to_parser ( sess, stream. 0 ) ;
1385
1376
let mut items = Vec :: new ( ) ;
1386
1377
@@ -1411,16 +1402,30 @@ pub mod __internal {
1411
1402
expand : fn ( TokenStream ) -> TokenStream ) ;
1412
1403
}
1413
1404
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
+
1414
1417
// Emulate scoped_thread_local!() here essentially
1415
1418
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
+ } ) ;
1418
1423
}
1419
1424
1420
1425
pub fn set_sess < F , R > ( cx : & ExtCtxt , f : F ) -> R
1421
1426
where F : FnOnce ( ) -> R
1422
1427
{
1423
- struct Reset { prev : ( * const ParseSess , Mark ) }
1428
+ struct Reset { prev : ProcMacroSess }
1424
1429
1425
1430
impl Drop for Reset {
1426
1431
fn drop ( & mut self ) {
@@ -1430,24 +1435,39 @@ pub mod __internal {
1430
1435
1431
1436
CURRENT_SESS . with ( |p| {
1432
1437
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
+ } ) ;
1434
1454
f ( )
1435
1455
} )
1436
1456
}
1437
1457
1438
1458
pub fn in_sess ( ) -> bool
1439
1459
{
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 ( )
1442
1461
}
1443
1462
1444
1463
pub fn with_sess < F , R > ( f : F ) -> R
1445
- where F : FnOnce ( ( & ParseSess , Mark ) ) -> R
1464
+ where F : FnOnce ( & ParseSess , & ProcMacroData ) -> R
1446
1465
{
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 )
1451
1471
}
1452
1472
}
1453
1473
0 commit comments