Skip to content

Commit d089fe9

Browse files
committedMar 14, 2018
Auto merge of #48811 - Zoxc:syntax-globals, r=michaelwoerister
Remove syntax and syntax_pos thread locals This moves `syntax` and `syntax_pos` globals into a struct which are pointed to by thread locals. Most of the changes here are indentation changes in test. It would probably be a good idea to ignore whitespace changes while reviewing. Some indentation is unchanged to avoid merge conflicts. r? @michaelwoerister
·
1.88.01.26.0
2 parents 24e679c + cbdf4ec commit d089fe9

File tree

29 files changed

+1257
-1043
lines changed

29 files changed

+1257
-1043
lines changed
 

‎src/Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎src/librustc/session/config.rs

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2391,6 +2391,7 @@ mod tests {
23912391
use super::{Externs, OutputType, OutputTypes};
23922392
use rustc_back::{PanicStrategy, RelroLevel};
23932393
use syntax::symbol::Symbol;
2394+
use syntax;
23942395

23952396
fn optgroups() -> getopts::Options {
23962397
let mut opts = getopts::Options::new();
@@ -2411,61 +2412,66 @@ mod tests {
24112412
// When the user supplies --test we should implicitly supply --cfg test
24122413
#[test]
24132414
fn test_switch_implies_cfg_test() {
2414-
let matches = &match optgroups().parse(&["--test".to_string()]) {
2415-
Ok(m) => m,
2416-
Err(f) => panic!("test_switch_implies_cfg_test: {}", f),
2417-
};
2418-
let registry = errors::registry::Registry::new(&[]);
2419-
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
2420-
let sess = build_session(sessopts, None, registry);
2421-
let cfg = build_configuration(&sess, cfg);
2422-
assert!(cfg.contains(&(Symbol::intern("test"), None)));
2415+
syntax::with_globals(|| {
2416+
let matches = &match optgroups().parse(&["--test".to_string()]) {
2417+
Ok(m) => m,
2418+
Err(f) => panic!("test_switch_implies_cfg_test: {}", f),
2419+
};
2420+
let registry = errors::registry::Registry::new(&[]);
2421+
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
2422+
let sess = build_session(sessopts, None, registry);
2423+
let cfg = build_configuration(&sess, cfg);
2424+
assert!(cfg.contains(&(Symbol::intern("test"), None)));
2425+
});
24232426
}
24242427

24252428
// When the user supplies --test and --cfg test, don't implicitly add
24262429
// another --cfg test
24272430
#[test]
24282431
fn test_switch_implies_cfg_test_unless_cfg_test() {
2429-
let matches = &match optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]) {
2430-
Ok(m) => m,
2431-
Err(f) => panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f),
2432-
};
2433-
let registry = errors::registry::Registry::new(&[]);
2434-
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
2435-
let sess = build_session(sessopts, None, registry);
2436-
let cfg = build_configuration(&sess, cfg);
2437-
let mut test_items = cfg.iter().filter(|&&(name, _)| name == "test");
2438-
assert!(test_items.next().is_some());
2439-
assert!(test_items.next().is_none());
2432+
syntax::with_globals(|| {
2433+
let matches = &match optgroups().parse(&["--test".to_string(),
2434+
"--cfg=test".to_string()]) {
2435+
Ok(m) => m,
2436+
Err(f) => panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f),
2437+
};
2438+
let registry = errors::registry::Registry::new(&[]);
2439+
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
2440+
let sess = build_session(sessopts, None, registry);
2441+
let cfg = build_configuration(&sess, cfg);
2442+
let mut test_items = cfg.iter().filter(|&&(name, _)| name == "test");
2443+
assert!(test_items.next().is_some());
2444+
assert!(test_items.next().is_none());
2445+
});
24402446
}
24412447

24422448
#[test]
24432449
fn test_can_print_warnings() {
2444-
{
2450+
syntax::with_globals(|| {
24452451
let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
24462452
let registry = errors::registry::Registry::new(&[]);
24472453
let (sessopts, _) = build_session_options_and_crate_config(&matches);
24482454
let sess = build_session(sessopts, None, registry);
24492455
assert!(!sess.diagnostic().flags.can_emit_warnings);
2450-
}
2456+
});
24512457

2452-
{
2458+
syntax::with_globals(|| {
24532459
let matches = optgroups()
24542460
.parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()])
24552461
.unwrap();
24562462
let registry = errors::registry::Registry::new(&[]);
24572463
let (sessopts, _) = build_session_options_and_crate_config(&matches);
24582464
let sess = build_session(sessopts, None, registry);
24592465
assert!(sess.diagnostic().flags.can_emit_warnings);
2460-
}
2466+
});
24612467

2462-
{
2468+
syntax::with_globals(|| {
24632469
let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
24642470
let registry = errors::registry::Registry::new(&[]);
24652471
let (sessopts, _) = build_session_options_and_crate_config(&matches);
24662472
let sess = build_session(sessopts, None, registry);
24672473
assert!(sess.diagnostic().flags.can_emit_warnings);
2468-
}
2474+
});
24692475
}
24702476

24712477
#[test]

‎src/librustc_driver/lib.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,17 @@ pub fn run_compiler<'a>(args: &[String],
447447
file_loader: Option<Box<FileLoader + 'static>>,
448448
emitter_dest: Option<Box<Write + Send>>)
449449
-> (CompileResult, Option<Session>)
450+
{
451+
syntax::with_globals(|| {
452+
run_compiler_impl(args, callbacks, file_loader, emitter_dest)
453+
})
454+
}
455+
456+
fn run_compiler_impl<'a>(args: &[String],
457+
callbacks: &mut CompilerCalls<'a>,
458+
file_loader: Option<Box<FileLoader + 'static>>,
459+
emitter_dest: Option<Box<Write + Send>>)
460+
-> (CompileResult, Option<Session>)
450461
{
451462
macro_rules! do_or_return {($expr: expr, $sess: expr) => {
452463
match $expr {

‎src/librustc_driver/test.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ use rustc::hir::map as hir_map;
2929
use rustc::session::{self, config};
3030
use rustc::session::config::{OutputFilenames, OutputTypes};
3131
use rustc_data_structures::sync::Lrc;
32+
use syntax;
3233
use syntax::ast;
3334
use syntax::abi::Abi;
3435
use syntax::codemap::{CodeMap, FilePathMapping, FileName};
@@ -93,9 +94,19 @@ fn errors(msgs: &[&str]) -> (Box<Emitter + Send>, usize) {
9394
}
9495

9596
fn test_env<F>(source_string: &str,
96-
(emitter, expected_err_count): (Box<Emitter + Send>, usize),
97+
args: (Box<Emitter + Send>, usize),
9798
body: F)
9899
where F: FnOnce(Env)
100+
{
101+
syntax::with_globals(|| {
102+
test_env_impl(source_string, args, body)
103+
});
104+
}
105+
106+
fn test_env_impl<F>(source_string: &str,
107+
(emitter, expected_err_count): (Box<Emitter + Send>, usize),
108+
body: F)
109+
where F: FnOnce(Env)
99110
{
100111
let mut options = config::basic_options();
101112
options.debugging_opts.verbose = true;

‎src/librustdoc/clean/cfg.rs

Lines changed: 466 additions & 450 deletions
Large diffs are not rendered by default.

‎src/librustdoc/lib.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ pub fn main() {
102102
const STACK_SIZE: usize = 32_000_000; // 32MB
103103
env_logger::init();
104104
let res = std::thread::Builder::new().stack_size(STACK_SIZE).spawn(move || {
105-
get_args().map(|args| main_args(&args)).unwrap_or(1)
105+
syntax::with_globals(move || {
106+
get_args().map(|args| main_args(&args)).unwrap_or(1)
107+
})
106108
}).unwrap().join().unwrap_or(101);
107109
process::exit(res as i32);
108110
}
@@ -554,7 +556,8 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
554556
});
555557

556558
let (tx, rx) = channel();
557-
rustc_driver::monitor(move || {
559+
560+
rustc_driver::monitor(move || syntax::with_globals(move || {
558561
use rustc::session::config::Input;
559562

560563
let (mut krate, renderinfo) =
@@ -623,7 +626,7 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
623626
let krate = pm.run_plugins(krate);
624627

625628
tx.send(f(Output { krate: krate, renderinfo: renderinfo, passes: passes })).unwrap();
626-
});
629+
}));
627630
rx.recv().unwrap()
628631
}
629632

‎src/librustdoc/test.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use rustc_resolve::MakeGlobMap;
3535
use syntax::ast;
3636
use syntax::codemap::CodeMap;
3737
use syntax::feature_gate::UnstableFeatures;
38+
use syntax::with_globals;
3839
use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName};
3940
use errors;
4041
use errors::emitter::ColorConfig;
@@ -518,7 +519,7 @@ impl Collector {
518519
let panic = io::set_panic(None);
519520
let print = io::set_print(None);
520521
match {
521-
rustc_driver::in_rustc_thread(move || {
522+
rustc_driver::in_rustc_thread(move || with_globals(move || {
522523
io::set_panic(panic);
523524
io::set_print(print);
524525
run_test(&test,
@@ -536,7 +537,7 @@ impl Collector {
536537
&opts,
537538
maybe_sysroot,
538539
linker)
539-
})
540+
}))
540541
} {
541542
Ok(()) => (),
542543
Err(err) => panic::resume_unwind(err),

‎src/libsyntax/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ crate-type = ["dylib"]
1212
bitflags = "1.0"
1313
serialize = { path = "../libserialize" }
1414
log = "0.4"
15+
scoped-tls = "0.1"
1516
syntax_pos = { path = "../libsyntax_pos" }
1617
rustc_cratesio_shim = { path = "../librustc_cratesio_shim" }
1718
rustc_errors = { path = "../librustc_errors" }

‎src/libsyntax/attr.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,10 @@ use ptr::P;
3030
use symbol::Symbol;
3131
use tokenstream::{TokenStream, TokenTree, Delimited};
3232
use util::ThinVec;
33+
use GLOBALS;
3334

34-
use std::cell::RefCell;
3535
use std::iter;
3636

37-
thread_local! {
38-
static USED_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new());
39-
static KNOWN_ATTRS: RefCell<Vec<u64>> = RefCell::new(Vec::new());
40-
}
41-
4237
enum AttrError {
4338
MultipleItem(Name),
4439
UnknownMetaItem(Name),
@@ -65,45 +60,49 @@ fn handle_errors(diag: &Handler, span: Span, error: AttrError) {
6560
pub fn mark_used(attr: &Attribute) {
6661
debug!("Marking {:?} as used.", attr);
6762
let AttrId(id) = attr.id;
68-
USED_ATTRS.with(|slot| {
63+
GLOBALS.with(|globals| {
64+
let mut slot = globals.used_attrs.lock();
6965
let idx = (id / 64) as usize;
7066
let shift = id % 64;
71-
if slot.borrow().len() <= idx {
72-
slot.borrow_mut().resize(idx + 1, 0);
67+
if slot.len() <= idx {
68+
slot.resize(idx + 1, 0);
7369
}
74-
slot.borrow_mut()[idx] |= 1 << shift;
70+
slot[idx] |= 1 << shift;
7571
});
7672
}
7773

7874
pub fn is_used(attr: &Attribute) -> bool {
7975
let AttrId(id) = attr.id;
80-
USED_ATTRS.with(|slot| {
76+
GLOBALS.with(|globals| {
77+
let slot = globals.used_attrs.lock();
8178
let idx = (id / 64) as usize;
8279
let shift = id % 64;
83-
slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0)
80+
slot.get(idx).map(|bits| bits & (1 << shift) != 0)
8481
.unwrap_or(false)
8582
})
8683
}
8784

8885
pub fn mark_known(attr: &Attribute) {
8986
debug!("Marking {:?} as known.", attr);
9087
let AttrId(id) = attr.id;
91-
KNOWN_ATTRS.with(|slot| {
88+
GLOBALS.with(|globals| {
89+
let mut slot = globals.known_attrs.lock();
9290
let idx = (id / 64) as usize;
9391
let shift = id % 64;
94-
if slot.borrow().len() <= idx {
95-
slot.borrow_mut().resize(idx + 1, 0);
92+
if slot.len() <= idx {
93+
slot.resize(idx + 1, 0);
9694
}
97-
slot.borrow_mut()[idx] |= 1 << shift;
95+
slot[idx] |= 1 << shift;
9896
});
9997
}
10098

10199
pub fn is_known(attr: &Attribute) -> bool {
102100
let AttrId(id) = attr.id;
103-
KNOWN_ATTRS.with(|slot| {
101+
GLOBALS.with(|globals| {
102+
let slot = globals.known_attrs.lock();
104103
let idx = (id / 64) as usize;
105104
let shift = id % 64;
106-
slot.borrow().get(idx).map(|bits| bits & (1 << shift) != 0)
105+
slot.get(idx).map(|bits| bits & (1 << shift) != 0)
107106
.unwrap_or(false)
108107
})
109108
}

‎src/libsyntax/fold.rs

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,7 @@ mod tests {
13861386
use util::parser_testing::{string_to_crate, matches_codepattern};
13871387
use print::pprust;
13881388
use fold;
1389+
use with_globals;
13891390
use super::*;
13901391

13911392
// this version doesn't care about getting comments or docstrings in.
@@ -1423,28 +1424,32 @@ mod tests {
14231424

14241425
// make sure idents get transformed everywhere
14251426
#[test] fn ident_transformation () {
1426-
let mut zz_fold = ToZzIdentFolder;
1427-
let ast = string_to_crate(
1428-
"#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string());
1429-
let folded_crate = zz_fold.fold_crate(ast);
1430-
assert_pred!(
1431-
matches_codepattern,
1432-
"matches_codepattern",
1433-
pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
1434-
"#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string());
1427+
with_globals(|| {
1428+
let mut zz_fold = ToZzIdentFolder;
1429+
let ast = string_to_crate(
1430+
"#[a] mod b {fn c (d : e, f : g) {h!(i,j,k);l;m}}".to_string());
1431+
let folded_crate = zz_fold.fold_crate(ast);
1432+
assert_pred!(
1433+
matches_codepattern,
1434+
"matches_codepattern",
1435+
pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
1436+
"#[zz]mod zz{fn zz(zz:zz,zz:zz){zz!(zz,zz,zz);zz;zz}}".to_string());
1437+
})
14351438
}
14361439

14371440
// even inside macro defs....
14381441
#[test] fn ident_transformation_in_defs () {
1439-
let mut zz_fold = ToZzIdentFolder;
1440-
let ast = string_to_crate(
1441-
"macro_rules! a {(b $c:expr $(d $e:token)f+ => \
1442-
(g $(d $d $e)+))} ".to_string());
1443-
let folded_crate = zz_fold.fold_crate(ast);
1444-
assert_pred!(
1445-
matches_codepattern,
1446-
"matches_codepattern",
1447-
pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
1448-
"macro_rules! zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string());
1442+
with_globals(|| {
1443+
let mut zz_fold = ToZzIdentFolder;
1444+
let ast = string_to_crate(
1445+
"macro_rules! a {(b $c:expr $(d $e:token)f+ => \
1446+
(g $(d $d $e)+))} ".to_string());
1447+
let folded_crate = zz_fold.fold_crate(ast);
1448+
assert_pred!(
1449+
matches_codepattern,
1450+
"matches_codepattern",
1451+
pprust::to_string(|s| fake_print_crate(s, &folded_crate)),
1452+
"macro_rules! zz((zz$zz:zz$(zz $zz:zz)zz+=>(zz$(zz$zz$zz)+)));".to_string());
1453+
})
14491454
}
14501455
}

‎src/libsyntax/lib.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@ extern crate std_unicode;
3939
pub extern crate rustc_errors as errors;
4040
extern crate syntax_pos;
4141
extern crate rustc_data_structures;
42+
#[macro_use] extern crate scoped_tls;
4243

4344
extern crate serialize as rustc_serialize; // used by deriving
4445

46+
use rustc_data_structures::sync::Lock;
47+
4548
// A variant of 'try!' that panics on an Err. This is used as a crutch on the
4649
// way towards a non-panic!-prone parser. It should be used for fatal parsing
4750
// errors; eventually we plan to convert all code using panictry to just use
@@ -72,6 +75,33 @@ macro_rules! unwrap_or {
7275
}
7376
}
7477

78+
struct Globals {
79+
used_attrs: Lock<Vec<u64>>,
80+
known_attrs: Lock<Vec<u64>>,
81+
syntax_pos_globals: syntax_pos::Globals,
82+
}
83+
84+
impl Globals {
85+
fn new() -> Globals {
86+
Globals {
87+
used_attrs: Lock::new(Vec::new()),
88+
known_attrs: Lock::new(Vec::new()),
89+
syntax_pos_globals: syntax_pos::Globals::new(),
90+
}
91+
}
92+
}
93+
94+
pub fn with_globals<F, R>(f: F) -> R
95+
where F: FnOnce() -> R
96+
{
97+
let globals = Globals::new();
98+
GLOBALS.set(&globals, || {
99+
syntax_pos::GLOBALS.set(&globals.syntax_pos_globals, f)
100+
})
101+
}
102+
103+
scoped_thread_local!(static GLOBALS: Globals);
104+
75105
#[macro_use]
76106
pub mod diagnostics {
77107
#[macro_use]

‎src/libsyntax/parse/lexer/mod.rs

Lines changed: 143 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,7 @@ mod tests {
17661766
use std::path::PathBuf;
17671767
use diagnostics::plugin::ErrorMap;
17681768
use rustc_data_structures::sync::Lock;
1769+
use with_globals;
17691770
fn mk_sess(cm: Lrc<CodeMap>) -> ParseSess {
17701771
let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()),
17711772
Some(cm.clone()),
@@ -1794,33 +1795,35 @@ mod tests {
17941795

17951796
#[test]
17961797
fn t1() {
1797-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1798-
let sh = mk_sess(cm.clone());
1799-
let mut string_reader = setup(&cm,
1800-
&sh,
1801-
"/* my source file */ fn main() { println!(\"zebra\"); }\n"
1802-
.to_string());
1803-
let id = Ident::from_str("fn");
1804-
assert_eq!(string_reader.next_token().tok, token::Comment);
1805-
assert_eq!(string_reader.next_token().tok, token::Whitespace);
1806-
let tok1 = string_reader.next_token();
1807-
let tok2 = TokenAndSpan {
1808-
tok: token::Ident(id),
1809-
sp: Span::new(BytePos(21), BytePos(23), NO_EXPANSION),
1810-
};
1811-
assert_eq!(tok1, tok2);
1812-
assert_eq!(string_reader.next_token().tok, token::Whitespace);
1813-
// the 'main' id is already read:
1814-
assert_eq!(string_reader.pos.clone(), BytePos(28));
1815-
// read another token:
1816-
let tok3 = string_reader.next_token();
1817-
let tok4 = TokenAndSpan {
1818-
tok: token::Ident(Ident::from_str("main")),
1819-
sp: Span::new(BytePos(24), BytePos(28), NO_EXPANSION),
1820-
};
1821-
assert_eq!(tok3, tok4);
1822-
// the lparen is already read:
1823-
assert_eq!(string_reader.pos.clone(), BytePos(29))
1798+
with_globals(|| {
1799+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1800+
let sh = mk_sess(cm.clone());
1801+
let mut string_reader = setup(&cm,
1802+
&sh,
1803+
"/* my source file */ fn main() { println!(\"zebra\"); }\n"
1804+
.to_string());
1805+
let id = Ident::from_str("fn");
1806+
assert_eq!(string_reader.next_token().tok, token::Comment);
1807+
assert_eq!(string_reader.next_token().tok, token::Whitespace);
1808+
let tok1 = string_reader.next_token();
1809+
let tok2 = TokenAndSpan {
1810+
tok: token::Ident(id),
1811+
sp: Span::new(BytePos(21), BytePos(23), NO_EXPANSION),
1812+
};
1813+
assert_eq!(tok1, tok2);
1814+
assert_eq!(string_reader.next_token().tok, token::Whitespace);
1815+
// the 'main' id is already read:
1816+
assert_eq!(string_reader.pos.clone(), BytePos(28));
1817+
// read another token:
1818+
let tok3 = string_reader.next_token();
1819+
let tok4 = TokenAndSpan {
1820+
tok: token::Ident(Ident::from_str("main")),
1821+
sp: Span::new(BytePos(24), BytePos(28), NO_EXPANSION),
1822+
};
1823+
assert_eq!(tok3, tok4);
1824+
// the lparen is already read:
1825+
assert_eq!(string_reader.pos.clone(), BytePos(29))
1826+
})
18241827
}
18251828

18261829
// check that the given reader produces the desired stream
@@ -1838,113 +1841,133 @@ mod tests {
18381841

18391842
#[test]
18401843
fn doublecolonparsing() {
1841-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1842-
let sh = mk_sess(cm.clone());
1843-
check_tokenization(setup(&cm, &sh, "a b".to_string()),
1844-
vec![mk_ident("a"), token::Whitespace, mk_ident("b")]);
1844+
with_globals(|| {
1845+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1846+
let sh = mk_sess(cm.clone());
1847+
check_tokenization(setup(&cm, &sh, "a b".to_string()),
1848+
vec![mk_ident("a"), token::Whitespace, mk_ident("b")]);
1849+
})
18451850
}
18461851

18471852
#[test]
18481853
fn dcparsing_2() {
1849-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1850-
let sh = mk_sess(cm.clone());
1851-
check_tokenization(setup(&cm, &sh, "a::b".to_string()),
1852-
vec![mk_ident("a"), token::ModSep, mk_ident("b")]);
1854+
with_globals(|| {
1855+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1856+
let sh = mk_sess(cm.clone());
1857+
check_tokenization(setup(&cm, &sh, "a::b".to_string()),
1858+
vec![mk_ident("a"), token::ModSep, mk_ident("b")]);
1859+
})
18531860
}
18541861

18551862
#[test]
18561863
fn dcparsing_3() {
1857-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1858-
let sh = mk_sess(cm.clone());
1859-
check_tokenization(setup(&cm, &sh, "a ::b".to_string()),
1860-
vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]);
1864+
with_globals(|| {
1865+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1866+
let sh = mk_sess(cm.clone());
1867+
check_tokenization(setup(&cm, &sh, "a ::b".to_string()),
1868+
vec![mk_ident("a"), token::Whitespace, token::ModSep, mk_ident("b")]);
1869+
})
18611870
}
18621871

18631872
#[test]
18641873
fn dcparsing_4() {
1865-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1866-
let sh = mk_sess(cm.clone());
1867-
check_tokenization(setup(&cm, &sh, "a:: b".to_string()),
1868-
vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]);
1874+
with_globals(|| {
1875+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1876+
let sh = mk_sess(cm.clone());
1877+
check_tokenization(setup(&cm, &sh, "a:: b".to_string()),
1878+
vec![mk_ident("a"), token::ModSep, token::Whitespace, mk_ident("b")]);
1879+
})
18691880
}
18701881

18711882
#[test]
18721883
fn character_a() {
1873-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1874-
let sh = mk_sess(cm.clone());
1875-
assert_eq!(setup(&cm, &sh, "'a'".to_string()).next_token().tok,
1876-
token::Literal(token::Char(Symbol::intern("a")), None));
1884+
with_globals(|| {
1885+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1886+
let sh = mk_sess(cm.clone());
1887+
assert_eq!(setup(&cm, &sh, "'a'".to_string()).next_token().tok,
1888+
token::Literal(token::Char(Symbol::intern("a")), None));
1889+
})
18771890
}
18781891

18791892
#[test]
18801893
fn character_space() {
1881-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1882-
let sh = mk_sess(cm.clone());
1883-
assert_eq!(setup(&cm, &sh, "' '".to_string()).next_token().tok,
1884-
token::Literal(token::Char(Symbol::intern(" ")), None));
1894+
with_globals(|| {
1895+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1896+
let sh = mk_sess(cm.clone());
1897+
assert_eq!(setup(&cm, &sh, "' '".to_string()).next_token().tok,
1898+
token::Literal(token::Char(Symbol::intern(" ")), None));
1899+
})
18851900
}
18861901

18871902
#[test]
18881903
fn character_escaped() {
1889-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1890-
let sh = mk_sess(cm.clone());
1891-
assert_eq!(setup(&cm, &sh, "'\\n'".to_string()).next_token().tok,
1892-
token::Literal(token::Char(Symbol::intern("\\n")), None));
1904+
with_globals(|| {
1905+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1906+
let sh = mk_sess(cm.clone());
1907+
assert_eq!(setup(&cm, &sh, "'\\n'".to_string()).next_token().tok,
1908+
token::Literal(token::Char(Symbol::intern("\\n")), None));
1909+
})
18931910
}
18941911

18951912
#[test]
18961913
fn lifetime_name() {
1897-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1898-
let sh = mk_sess(cm.clone());
1899-
assert_eq!(setup(&cm, &sh, "'abc".to_string()).next_token().tok,
1900-
token::Lifetime(Ident::from_str("'abc")));
1914+
with_globals(|| {
1915+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1916+
let sh = mk_sess(cm.clone());
1917+
assert_eq!(setup(&cm, &sh, "'abc".to_string()).next_token().tok,
1918+
token::Lifetime(Ident::from_str("'abc")));
1919+
})
19011920
}
19021921

19031922
#[test]
19041923
fn raw_string() {
1905-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1906-
let sh = mk_sess(cm.clone());
1907-
assert_eq!(setup(&cm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string())
1908-
.next_token()
1909-
.tok,
1910-
token::Literal(token::StrRaw(Symbol::intern("\"#a\\b\x00c\""), 3), None));
1924+
with_globals(|| {
1925+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1926+
let sh = mk_sess(cm.clone());
1927+
assert_eq!(setup(&cm, &sh, "r###\"\"#a\\b\x00c\"\"###".to_string())
1928+
.next_token()
1929+
.tok,
1930+
token::Literal(token::StrRaw(Symbol::intern("\"#a\\b\x00c\""), 3), None));
1931+
})
19111932
}
19121933

19131934
#[test]
19141935
fn literal_suffixes() {
1915-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1916-
let sh = mk_sess(cm.clone());
1917-
macro_rules! test {
1918-
($input: expr, $tok_type: ident, $tok_contents: expr) => {{
1919-
assert_eq!(setup(&cm, &sh, format!("{}suffix", $input)).next_token().tok,
1920-
token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
1921-
Some(Symbol::intern("suffix"))));
1922-
// with a whitespace separator:
1923-
assert_eq!(setup(&cm, &sh, format!("{} suffix", $input)).next_token().tok,
1924-
token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
1925-
None));
1926-
}}
1927-
}
1928-
1929-
test!("'a'", Char, "a");
1930-
test!("b'a'", Byte, "a");
1931-
test!("\"a\"", Str_, "a");
1932-
test!("b\"a\"", ByteStr, "a");
1933-
test!("1234", Integer, "1234");
1934-
test!("0b101", Integer, "0b101");
1935-
test!("0xABC", Integer, "0xABC");
1936-
test!("1.0", Float, "1.0");
1937-
test!("1.0e10", Float, "1.0e10");
1938-
1939-
assert_eq!(setup(&cm, &sh, "2us".to_string()).next_token().tok,
1940-
token::Literal(token::Integer(Symbol::intern("2")),
1941-
Some(Symbol::intern("us"))));
1942-
assert_eq!(setup(&cm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok,
1943-
token::Literal(token::StrRaw(Symbol::intern("raw"), 3),
1944-
Some(Symbol::intern("suffix"))));
1945-
assert_eq!(setup(&cm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok,
1946-
token::Literal(token::ByteStrRaw(Symbol::intern("raw"), 3),
1947-
Some(Symbol::intern("suffix"))));
1936+
with_globals(|| {
1937+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1938+
let sh = mk_sess(cm.clone());
1939+
macro_rules! test {
1940+
($input: expr, $tok_type: ident, $tok_contents: expr) => {{
1941+
assert_eq!(setup(&cm, &sh, format!("{}suffix", $input)).next_token().tok,
1942+
token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
1943+
Some(Symbol::intern("suffix"))));
1944+
// with a whitespace separator:
1945+
assert_eq!(setup(&cm, &sh, format!("{} suffix", $input)).next_token().tok,
1946+
token::Literal(token::$tok_type(Symbol::intern($tok_contents)),
1947+
None));
1948+
}}
1949+
}
1950+
1951+
test!("'a'", Char, "a");
1952+
test!("b'a'", Byte, "a");
1953+
test!("\"a\"", Str_, "a");
1954+
test!("b\"a\"", ByteStr, "a");
1955+
test!("1234", Integer, "1234");
1956+
test!("0b101", Integer, "0b101");
1957+
test!("0xABC", Integer, "0xABC");
1958+
test!("1.0", Float, "1.0");
1959+
test!("1.0e10", Float, "1.0e10");
1960+
1961+
assert_eq!(setup(&cm, &sh, "2us".to_string()).next_token().tok,
1962+
token::Literal(token::Integer(Symbol::intern("2")),
1963+
Some(Symbol::intern("us"))));
1964+
assert_eq!(setup(&cm, &sh, "r###\"raw\"###suffix".to_string()).next_token().tok,
1965+
token::Literal(token::StrRaw(Symbol::intern("raw"), 3),
1966+
Some(Symbol::intern("suffix"))));
1967+
assert_eq!(setup(&cm, &sh, "br###\"raw\"###suffix".to_string()).next_token().tok,
1968+
token::Literal(token::ByteStrRaw(Symbol::intern("raw"), 3),
1969+
Some(Symbol::intern("suffix"))));
1970+
})
19481971
}
19491972

19501973
#[test]
@@ -1956,27 +1979,31 @@ mod tests {
19561979

19571980
#[test]
19581981
fn nested_block_comments() {
1959-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1960-
let sh = mk_sess(cm.clone());
1961-
let mut lexer = setup(&cm, &sh, "/* /* */ */'a'".to_string());
1962-
match lexer.next_token().tok {
1963-
token::Comment => {}
1964-
_ => panic!("expected a comment!"),
1965-
}
1966-
assert_eq!(lexer.next_token().tok,
1967-
token::Literal(token::Char(Symbol::intern("a")), None));
1982+
with_globals(|| {
1983+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1984+
let sh = mk_sess(cm.clone());
1985+
let mut lexer = setup(&cm, &sh, "/* /* */ */'a'".to_string());
1986+
match lexer.next_token().tok {
1987+
token::Comment => {}
1988+
_ => panic!("expected a comment!"),
1989+
}
1990+
assert_eq!(lexer.next_token().tok,
1991+
token::Literal(token::Char(Symbol::intern("a")), None));
1992+
})
19681993
}
19691994

19701995
#[test]
19711996
fn crlf_comments() {
1972-
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1973-
let sh = mk_sess(cm.clone());
1974-
let mut lexer = setup(&cm, &sh, "// test\r\n/// test\r\n".to_string());
1975-
let comment = lexer.next_token();
1976-
assert_eq!(comment.tok, token::Comment);
1977-
assert_eq!((comment.sp.lo(), comment.sp.hi()), (BytePos(0), BytePos(7)));
1978-
assert_eq!(lexer.next_token().tok, token::Whitespace);
1979-
assert_eq!(lexer.next_token().tok,
1980-
token::DocComment(Symbol::intern("/// test")));
1997+
with_globals(|| {
1998+
let cm = Lrc::new(CodeMap::new(FilePathMapping::empty()));
1999+
let sh = mk_sess(cm.clone());
2000+
let mut lexer = setup(&cm, &sh, "// test\r\n/// test\r\n".to_string());
2001+
let comment = lexer.next_token();
2002+
assert_eq!(comment.tok, token::Comment);
2003+
assert_eq!((comment.sp.lo(), comment.sp.hi()), (BytePos(0), BytePos(7)));
2004+
assert_eq!(lexer.next_token().tok, token::Whitespace);
2005+
assert_eq!(lexer.next_token().tok,
2006+
token::DocComment(Symbol::intern("/// test")));
2007+
})
19812008
}
19822009
}

‎src/libsyntax/parse/mod.rs

Lines changed: 322 additions & 287 deletions
Large diffs are not rendered by default.

‎src/libsyntax/print/pprust.rs

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3178,36 +3178,41 @@ mod tests {
31783178
use ast;
31793179
use codemap;
31803180
use syntax_pos;
3181+
use with_globals;
31813182

31823183
#[test]
31833184
fn test_fun_to_string() {
3184-
let abba_ident = ast::Ident::from_str("abba");
3185+
with_globals(|| {
3186+
let abba_ident = ast::Ident::from_str("abba");
31853187

3186-
let decl = ast::FnDecl {
3187-
inputs: Vec::new(),
3188-
output: ast::FunctionRetTy::Default(syntax_pos::DUMMY_SP),
3189-
variadic: false
3190-
};
3191-
let generics = ast::Generics::default();
3192-
assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal,
3193-
ast::Constness::NotConst,
3194-
abba_ident, &generics),
3195-
"fn abba()");
3188+
let decl = ast::FnDecl {
3189+
inputs: Vec::new(),
3190+
output: ast::FunctionRetTy::Default(syntax_pos::DUMMY_SP),
3191+
variadic: false
3192+
};
3193+
let generics = ast::Generics::default();
3194+
assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal,
3195+
ast::Constness::NotConst,
3196+
abba_ident, &generics),
3197+
"fn abba()");
3198+
})
31963199
}
31973200

31983201
#[test]
31993202
fn test_variant_to_string() {
3200-
let ident = ast::Ident::from_str("principal_skinner");
3201-
3202-
let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ {
3203-
name: ident,
3204-
attrs: Vec::new(),
3205-
// making this up as I go.... ?
3206-
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
3207-
disr_expr: None,
3208-
});
3209-
3210-
let varstr = variant_to_string(&var);
3211-
assert_eq!(varstr, "principal_skinner");
3203+
with_globals(|| {
3204+
let ident = ast::Ident::from_str("principal_skinner");
3205+
3206+
let var = codemap::respan(syntax_pos::DUMMY_SP, ast::Variant_ {
3207+
name: ident,
3208+
attrs: Vec::new(),
3209+
// making this up as I go.... ?
3210+
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
3211+
disr_expr: None,
3212+
});
3213+
3214+
let varstr = variant_to_string(&var);
3215+
assert_eq!(varstr, "principal_skinner");
3216+
})
32123217
}
32133218
}

‎src/libsyntax/test_snippet.rs

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use std::str;
1818
use std::sync::{Arc, Mutex};
1919
use std::path::Path;
2020
use syntax_pos::{BytePos, NO_EXPANSION, Span, MultiSpan};
21+
use with_globals;
2122

2223
/// Identify a position in the text by the Nth occurrence of a string.
2324
struct Position {
@@ -46,37 +47,39 @@ impl<T: Write> Write for Shared<T> {
4647
}
4748

4849
fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &str) {
49-
let output = Arc::new(Mutex::new(Vec::new()));
50+
with_globals(|| {
51+
let output = Arc::new(Mutex::new(Vec::new()));
5052

51-
let code_map = Lrc::new(CodeMap::new(FilePathMapping::empty()));
52-
code_map.new_filemap_and_lines(Path::new("test.rs"), &file_text);
53+
let code_map = Lrc::new(CodeMap::new(FilePathMapping::empty()));
54+
code_map.new_filemap_and_lines(Path::new("test.rs"), &file_text);
5355

54-
let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end);
55-
let mut msp = MultiSpan::from_span(primary_span);
56-
for span_label in span_labels {
57-
let span = make_span(&file_text, &span_label.start, &span_label.end);
58-
msp.push_span_label(span, span_label.label.to_string());
59-
println!("span: {:?} label: {:?}", span, span_label.label);
60-
println!("text: {:?}", code_map.span_to_snippet(span));
61-
}
56+
let primary_span = make_span(&file_text, &span_labels[0].start, &span_labels[0].end);
57+
let mut msp = MultiSpan::from_span(primary_span);
58+
for span_label in span_labels {
59+
let span = make_span(&file_text, &span_label.start, &span_label.end);
60+
msp.push_span_label(span, span_label.label.to_string());
61+
println!("span: {:?} label: {:?}", span, span_label.label);
62+
println!("text: {:?}", code_map.span_to_snippet(span));
63+
}
6264

63-
let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }),
64-
Some(code_map.clone()),
65-
false,
66-
false);
67-
let handler = Handler::with_emitter(true, false, Box::new(emitter));
68-
handler.span_err(msp, "foo");
65+
let emitter = EmitterWriter::new(Box::new(Shared { data: output.clone() }),
66+
Some(code_map.clone()),
67+
false,
68+
false);
69+
let handler = Handler::with_emitter(true, false, Box::new(emitter));
70+
handler.span_err(msp, "foo");
6971

70-
assert!(expected_output.chars().next() == Some('\n'),
71-
"expected output should begin with newline");
72-
let expected_output = &expected_output[1..];
72+
assert!(expected_output.chars().next() == Some('\n'),
73+
"expected output should begin with newline");
74+
let expected_output = &expected_output[1..];
7375

74-
let bytes = output.lock().unwrap();
75-
let actual_output = str::from_utf8(&bytes).unwrap();
76-
println!("expected output:\n------\n{}------", expected_output);
77-
println!("actual output:\n------\n{}------", actual_output);
76+
let bytes = output.lock().unwrap();
77+
let actual_output = str::from_utf8(&bytes).unwrap();
78+
println!("expected output:\n------\n{}------", expected_output);
79+
println!("actual output:\n------\n{}------", actual_output);
7880

79-
assert!(expected_output == actual_output)
81+
assert!(expected_output == actual_output)
82+
})
8083
}
8184

8285
fn make_span(file_text: &str, start: &Position, end: &Position) -> Span {

‎src/libsyntax/tokenstream.rs

Lines changed: 50 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -599,6 +599,7 @@ impl Hash for ThinTokenStream {
599599
mod tests {
600600
use super::*;
601601
use syntax::ast::Ident;
602+
use with_globals;
602603
use syntax_pos::{Span, BytePos, NO_EXPANSION};
603604
use parse::token::Token;
604605
use util::parser_testing::string_to_stream;
@@ -613,67 +614,83 @@ mod tests {
613614

614615
#[test]
615616
fn test_concat() {
616-
let test_res = string_to_ts("foo::bar::baz");
617-
let test_fst = string_to_ts("foo::bar");
618-
let test_snd = string_to_ts("::baz");
619-
let eq_res = TokenStream::concat(vec![test_fst, test_snd]);
620-
assert_eq!(test_res.trees().count(), 5);
621-
assert_eq!(eq_res.trees().count(), 5);
622-
assert_eq!(test_res.eq_unspanned(&eq_res), true);
617+
with_globals(|| {
618+
let test_res = string_to_ts("foo::bar::baz");
619+
let test_fst = string_to_ts("foo::bar");
620+
let test_snd = string_to_ts("::baz");
621+
let eq_res = TokenStream::concat(vec![test_fst, test_snd]);
622+
assert_eq!(test_res.trees().count(), 5);
623+
assert_eq!(eq_res.trees().count(), 5);
624+
assert_eq!(test_res.eq_unspanned(&eq_res), true);
625+
})
623626
}
624627

625628
#[test]
626629
fn test_to_from_bijection() {
627-
let test_start = string_to_ts("foo::bar(baz)");
628-
let test_end = test_start.trees().collect();
629-
assert_eq!(test_start, test_end)
630+
with_globals(|| {
631+
let test_start = string_to_ts("foo::bar(baz)");
632+
let test_end = test_start.trees().collect();
633+
assert_eq!(test_start, test_end)
634+
})
630635
}
631636

632637
#[test]
633638
fn test_eq_0() {
634-
let test_res = string_to_ts("foo");
635-
let test_eqs = string_to_ts("foo");
636-
assert_eq!(test_res, test_eqs)
639+
with_globals(|| {
640+
let test_res = string_to_ts("foo");
641+
let test_eqs = string_to_ts("foo");
642+
assert_eq!(test_res, test_eqs)
643+
})
637644
}
638645

639646
#[test]
640647
fn test_eq_1() {
641-
let test_res = string_to_ts("::bar::baz");
642-
let test_eqs = string_to_ts("::bar::baz");
643-
assert_eq!(test_res, test_eqs)
648+
with_globals(|| {
649+
let test_res = string_to_ts("::bar::baz");
650+
let test_eqs = string_to_ts("::bar::baz");
651+
assert_eq!(test_res, test_eqs)
652+
})
644653
}
645654

646655
#[test]
647656
fn test_eq_3() {
648-
let test_res = string_to_ts("");
649-
let test_eqs = string_to_ts("");
650-
assert_eq!(test_res, test_eqs)
657+
with_globals(|| {
658+
let test_res = string_to_ts("");
659+
let test_eqs = string_to_ts("");
660+
assert_eq!(test_res, test_eqs)
661+
})
651662
}
652663

653664
#[test]
654665
fn test_diseq_0() {
655-
let test_res = string_to_ts("::bar::baz");
656-
let test_eqs = string_to_ts("bar::baz");
657-
assert_eq!(test_res == test_eqs, false)
666+
with_globals(|| {
667+
let test_res = string_to_ts("::bar::baz");
668+
let test_eqs = string_to_ts("bar::baz");
669+
assert_eq!(test_res == test_eqs, false)
670+
})
658671
}
659672

660673
#[test]
661674
fn test_diseq_1() {
662-
let test_res = string_to_ts("(bar,baz)");
663-
let test_eqs = string_to_ts("bar,baz");
664-
assert_eq!(test_res == test_eqs, false)
675+
with_globals(|| {
676+
let test_res = string_to_ts("(bar,baz)");
677+
let test_eqs = string_to_ts("bar,baz");
678+
assert_eq!(test_res == test_eqs, false)
679+
})
665680
}
666681

667682
#[test]
668683
fn test_is_empty() {
669-
let test0: TokenStream = Vec::<TokenTree>::new().into_iter().collect();
670-
let test1: TokenStream =
671-
TokenTree::Token(sp(0, 1), Token::Ident(Ident::from_str("a"))).into();
672-
let test2 = string_to_ts("foo(bar::baz)");
673-
674-
assert_eq!(test0.is_empty(), true);
675-
assert_eq!(test1.is_empty(), false);
676-
assert_eq!(test2.is_empty(), false);
684+
with_globals(|| {
685+
let test0: TokenStream = Vec::<TokenTree>::new().into_iter().collect();
686+
let test1: TokenStream =
687+
TokenTree::Token(sp(0, 1), Token::Ident(Ident::from_str("a"))).into();
688+
let test2 = string_to_ts("foo(bar::baz)");
689+
690+
assert_eq!(test0.is_empty(), true);
691+
assert_eq!(test1.is_empty(), false);
692+
assert_eq!(test2.is_empty(), false);
693+
})
677694
}
678695

679696
#[test]

‎src/libsyntax_pos/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ crate-type = ["dylib"]
1111
[dependencies]
1212
serialize = { path = "../libserialize" }
1313
rustc_data_structures = { path = "../librustc_data_structures" }
14+
scoped-tls = { version = "0.1.1", features = ["nightly"] }
1415
unicode-width = "0.1.4"

‎src/libsyntax_pos/hygiene.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@
1515
//! and definition contexts*. J. Funct. Program. 22, 2 (March 2012), 181-216.
1616
//! DOI=10.1017/S0956796812000093 <http://dx.doi.org/10.1017/S0956796812000093>
1717
18+
use GLOBALS;
1819
use Span;
1920
use symbol::{Ident, Symbol};
2021

2122
use serialize::{Encodable, Decodable, Encoder, Decoder};
22-
use std::cell::RefCell;
2323
use std::collections::HashMap;
2424
use std::fmt;
2525

@@ -119,15 +119,15 @@ impl Mark {
119119
}
120120
}
121121

122-
struct HygieneData {
122+
pub struct HygieneData {
123123
marks: Vec<MarkData>,
124124
syntax_contexts: Vec<SyntaxContextData>,
125125
markings: HashMap<(SyntaxContext, Mark), SyntaxContext>,
126126
gensym_to_ctxt: HashMap<Symbol, SyntaxContext>,
127127
}
128128

129129
impl HygieneData {
130-
fn new() -> Self {
130+
pub fn new() -> Self {
131131
HygieneData {
132132
marks: vec![MarkData {
133133
parent: Mark::root(),
@@ -145,10 +145,7 @@ impl HygieneData {
145145
}
146146

147147
fn with<T, F: FnOnce(&mut HygieneData) -> T>(f: F) -> T {
148-
thread_local! {
149-
static HYGIENE_DATA: RefCell<HygieneData> = RefCell::new(HygieneData::new());
150-
}
151-
HYGIENE_DATA.with(|data| f(&mut *data.borrow_mut()))
148+
GLOBALS.with(|globals| f(&mut *globals.hygiene_data.borrow_mut()))
152149
}
153150
}
154151

‎src/libsyntax_pos/lib.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ use std::ops::{Add, Sub};
3535
use std::path::PathBuf;
3636

3737
use rustc_data_structures::stable_hasher::StableHasher;
38-
use rustc_data_structures::sync::Lrc;
38+
use rustc_data_structures::sync::{Lrc, Lock};
3939

4040
extern crate rustc_data_structures;
4141

42+
#[macro_use]
43+
extern crate scoped_tls;
44+
4245
use serialize::{Encodable, Decodable, Encoder, Decoder};
4346

4447
extern crate serialize;
@@ -54,6 +57,24 @@ pub use span_encoding::{Span, DUMMY_SP};
5457

5558
pub mod symbol;
5659

60+
pub struct Globals {
61+
symbol_interner: Lock<symbol::Interner>,
62+
span_interner: Lock<span_encoding::SpanInterner>,
63+
hygiene_data: Lock<hygiene::HygieneData>,
64+
}
65+
66+
impl Globals {
67+
pub fn new() -> Globals {
68+
Globals {
69+
symbol_interner: Lock::new(symbol::Interner::fresh()),
70+
span_interner: Lock::new(span_encoding::SpanInterner::default()),
71+
hygiene_data: Lock::new(hygiene::HygieneData::new()),
72+
}
73+
}
74+
}
75+
76+
scoped_thread_local!(pub static GLOBALS: Globals);
77+
5778
/// Differentiates between real files and common virtual files
5879
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)]
5980
pub enum FileName {

‎src/libsyntax_pos/span_encoding.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
// The encoding format for inline spans were obtained by optimizing over crates in rustc/libstd.
1515
// See https://internals.rust-lang.org/t/rfc-compiler-refactoring-spans/1357/28
1616

17+
use GLOBALS;
1718
use {BytePos, SpanData};
1819
use hygiene::SyntaxContext;
1920

2021
use rustc_data_structures::fx::FxHashMap;
21-
use std::cell::RefCell;
2222
use std::hash::{Hash, Hasher};
2323

2424
/// A compressed span.
@@ -133,7 +133,7 @@ fn decode(span: Span) -> SpanData {
133133
}
134134

135135
#[derive(Default)]
136-
struct SpanInterner {
136+
pub struct SpanInterner {
137137
spans: FxHashMap<SpanData, u32>,
138138
span_data: Vec<SpanData>,
139139
}
@@ -156,11 +156,8 @@ impl SpanInterner {
156156
}
157157
}
158158

159-
// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
159+
// If an interner exists, return it. Otherwise, prepare a fresh one.
160160
#[inline]
161161
fn with_span_interner<T, F: FnOnce(&mut SpanInterner) -> T>(f: F) -> T {
162-
thread_local!(static INTERNER: RefCell<SpanInterner> = {
163-
RefCell::new(SpanInterner::default())
164-
});
165-
INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
162+
GLOBALS.with(|globals| f(&mut *globals.span_interner.lock()))
166163
}

‎src/libsyntax_pos/symbol.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
//! type, and vice versa.
1414
1515
use hygiene::SyntaxContext;
16+
use GLOBALS;
1617

1718
use serialize::{Decodable, Decoder, Encodable, Encoder};
18-
use std::cell::RefCell;
1919
use std::collections::HashMap;
2020
use std::fmt;
2121

@@ -247,7 +247,7 @@ macro_rules! declare_keywords {(
247247
}
248248

249249
impl Interner {
250-
fn fresh() -> Self {
250+
pub fn fresh() -> Self {
251251
Interner::prefill(&[$($string,)*])
252252
}
253253
}
@@ -330,12 +330,10 @@ declare_keywords! {
330330
(60, Union, "union")
331331
}
332332

333-
// If an interner exists in TLS, return it. Otherwise, prepare a fresh one.
333+
// If an interner exists, return it. Otherwise, prepare a fresh one.
334+
#[inline]
334335
fn with_interner<T, F: FnOnce(&mut Interner) -> T>(f: F) -> T {
335-
thread_local!(static INTERNER: RefCell<Interner> = {
336-
RefCell::new(Interner::fresh())
337-
});
338-
INTERNER.with(|interner| f(&mut *interner.borrow_mut()))
336+
GLOBALS.with(|globals| f(&mut *globals.symbol_interner.lock()))
339337
}
340338

341339
/// Represents a string stored in the thread-local interner. Because the
@@ -422,6 +420,7 @@ impl Encodable for InternedString {
422420
#[cfg(test)]
423421
mod tests {
424422
use super::*;
423+
use Globals;
425424

426425
#[test]
427426
fn interner_tests() {
@@ -444,7 +443,9 @@ mod tests {
444443

445444
#[test]
446445
fn without_first_quote_test() {
447-
let i = Ident::from_str("'break");
448-
assert_eq!(i.without_first_quote().name, keywords::Break.name());
446+
GLOBALS.set(&Globals::new(), || {
447+
let i = Ident::from_str("'break");
448+
assert_eq!(i.without_first_quote().name, keywords::Break.name());
449+
});
449450
}
450451
}

‎src/test/run-fail-fulldeps/qquote.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ use syntax::symbol::Symbol;
2424
use syntax_pos::DUMMY_SP;
2525

2626
fn main() {
27+
syntax::with_globals(|| run());
28+
}
29+
30+
fn run() {
2731
let ps = syntax::parse::ParseSess::new(codemap::FilePathMapping::empty());
2832
let mut resolver = syntax::ext::base::DummyResolver;
2933
let mut cx = syntax::ext::base::ExtCtxt::new(

‎src/test/run-make/issue-19371/foo.rs

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,20 @@ fn basic_sess(sysroot: PathBuf) -> (Session, Rc<CStore>, Box<TransCrate>) {
6969
}
7070

7171
fn compile(code: String, output: PathBuf, sysroot: PathBuf) {
72-
let (sess, cstore, trans) = basic_sess(sysroot);
73-
let control = CompileController::basic();
74-
let input = Input::Str { name: FileName::Anon, input: code };
75-
let _ = compile_input(
76-
trans,
77-
&sess,
78-
&cstore,
79-
&None,
80-
&input,
81-
&None,
82-
&Some(output),
83-
None,
84-
&control
85-
);
72+
syntax::with_globals(|| {
73+
let (sess, cstore, trans) = basic_sess(sysroot);
74+
let control = CompileController::basic();
75+
let input = Input::Str { name: FileName::Anon, input: code };
76+
let _ = compile_input(
77+
trans,
78+
&sess,
79+
&cstore,
80+
&None,
81+
&input,
82+
&None,
83+
&Some(output),
84+
None,
85+
&control
86+
);
87+
});
8688
}

‎src/test/run-pass-fulldeps/ast_stmt_expr_attr.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ fn reject_stmt_parse(es: &str) {
115115
}
116116

117117
fn main() {
118+
syntax::with_globals(|| run());
119+
}
120+
121+
fn run() {
118122
let both = &["#[attr]", "#![attr]"];
119123
let outer = &["#[attr]"];
120124
let none = &[];

‎src/test/run-pass-fulldeps/issue-35829.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ use syntax::ptr::P;
2727
use rustc_data_structures::sync::Lrc;
2828

2929
fn main() {
30+
syntax::with_globals(|| run());
31+
}
32+
33+
fn run() {
3034
let parse_sess = ParseSess::new(FilePathMapping::empty());
3135
let exp_cfg = ExpansionConfig::default("issue_35829".to_owned());
3236
let mut resolver = DummyResolver;

‎src/test/run-pass-fulldeps/pprust-expr-roundtrip.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,11 @@ impl Folder for AddParens {
221221
}
222222
}
223223

224-
225224
fn main() {
225+
syntax::with_globals(|| run());
226+
}
227+
228+
fn run() {
226229
let ps = ParseSess::new(FilePathMapping::empty());
227230

228231
iter_exprs(2, &mut |e| {

‎src/test/run-pass-fulldeps/qquote.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ use syntax::symbol::Symbol;
2121
use syntax_pos::DUMMY_SP;
2222

2323
fn main() {
24+
syntax::with_globals(|| run());
25+
}
26+
27+
fn run() {
2428
let ps = syntax::parse::ParseSess::new(FilePathMapping::empty());
2529
let mut resolver = syntax::ext::base::DummyResolver;
2630
let mut cx = syntax::ext::base::ExtCtxt::new(

‎src/tools/error_index_generator/main.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,10 @@ fn main() {
263263
*slot.borrow_mut() = Some((None, String::from("https://play.rust-lang.org/")));
264264
});
265265
let (format, dst) = parse_args();
266-
if let Err(e) = main_with_result(format, &dst) {
266+
let result = syntax::with_globals(move || {
267+
main_with_result(format, &dst)
268+
});
269+
if let Err(e) = result {
267270
panic!("{}", e.description());
268271
}
269272
}

‎src/tools/tidy/src/deps.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ static WHITELIST: &'static [Crate] = &[
9393
Crate("regex-syntax"),
9494
Crate("remove_dir_all"),
9595
Crate("rustc-demangle"),
96+
Crate("scoped-tls"),
9697
Crate("smallvec"),
9798
Crate("stable_deref_trait"),
9899
Crate("tempdir"),

0 commit comments

Comments
 (0)
Please sign in to comment.