Skip to content

Commit 871bf33

Browse files
Rollup merge of rust-lang#67614 - Mark-Simulacrum:global-callbacks, r=Zoxc
Set callbacks globally This sets the callbacks from syntax and rustc_errors just once, utilizing static (rather than thread-local) storage.
2 parents 0bb17cd + 4dcc627 commit 871bf33

File tree

9 files changed

+99
-75
lines changed

9 files changed

+99
-75
lines changed

Diff for: src/librustc/ty/context.rs

+1-55
Original file line numberDiff line numberDiff line change
@@ -1610,13 +1610,11 @@ pub mod tls {
16101610

16111611
use crate::dep_graph::TaskDeps;
16121612
use crate::ty::query;
1613-
use errors::{Diagnostic, TRACK_DIAGNOSTICS};
1613+
use errors::Diagnostic;
16141614
use rustc_data_structures::sync::{self, Lock, Lrc};
16151615
use rustc_data_structures::thin_vec::ThinVec;
16161616
use rustc_data_structures::OnDrop;
1617-
use std::fmt;
16181617
use std::mem;
1619-
use syntax_pos;
16201618

16211619
#[cfg(not(parallel_compiler))]
16221620
use std::cell::Cell;
@@ -1692,58 +1690,6 @@ pub mod tls {
16921690
TLV.with(|tlv| tlv.get())
16931691
}
16941692

1695-
/// This is a callback from libsyntax as it cannot access the implicit state
1696-
/// in librustc otherwise.
1697-
fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1698-
with_opt(|tcx| {
1699-
if let Some(tcx) = tcx {
1700-
write!(f, "{}", tcx.sess.source_map().span_to_string(span))
1701-
} else {
1702-
syntax_pos::default_span_debug(span, f)
1703-
}
1704-
})
1705-
}
1706-
1707-
/// This is a callback from libsyntax as it cannot access the implicit state
1708-
/// in librustc otherwise. It is used to when diagnostic messages are
1709-
/// emitted and stores them in the current query, if there is one.
1710-
fn track_diagnostic(diagnostic: &Diagnostic) {
1711-
with_context_opt(|icx| {
1712-
if let Some(icx) = icx {
1713-
if let Some(ref diagnostics) = icx.diagnostics {
1714-
let mut diagnostics = diagnostics.lock();
1715-
diagnostics.extend(Some(diagnostic.clone()));
1716-
}
1717-
}
1718-
})
1719-
}
1720-
1721-
/// Sets up the callbacks from libsyntax on the current thread.
1722-
pub fn with_thread_locals<F, R>(f: F) -> R
1723-
where
1724-
F: FnOnce() -> R,
1725-
{
1726-
syntax_pos::SPAN_DEBUG.with(|span_dbg| {
1727-
let original_span_debug = span_dbg.get();
1728-
span_dbg.set(span_debug);
1729-
1730-
let _on_drop = OnDrop(move || {
1731-
span_dbg.set(original_span_debug);
1732-
});
1733-
1734-
TRACK_DIAGNOSTICS.with(|current| {
1735-
let original = current.get();
1736-
current.set(track_diagnostic);
1737-
1738-
let _on_drop = OnDrop(move || {
1739-
current.set(original);
1740-
});
1741-
1742-
f()
1743-
})
1744-
})
1745-
}
1746-
17471693
/// Sets `context` as the new current `ImplicitCtxt` for the duration of the function `f`.
17481694
#[inline]
17491695
pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R

Diff for: src/librustc/ty/query/job.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -435,13 +435,14 @@ pub unsafe fn handle_deadlock() {
435435
let syntax_pos_globals =
436436
syntax_pos::GLOBALS.with(|syntax_pos_globals| syntax_pos_globals as *const _);
437437
let syntax_pos_globals = &*syntax_pos_globals;
438+
let syntax_globals = syntax::GLOBALS.with(|syntax_globals| syntax_globals as *const _);
439+
let syntax_globals = &*syntax_globals;
438440
thread::spawn(move || {
439441
tls::GCX_PTR.set(gcx_ptr, || {
440-
syntax_pos::GLOBALS.set(syntax_pos_globals, || {
441-
syntax_pos::GLOBALS.set(syntax_pos_globals, || {
442-
tls::with_thread_locals(|| tls::with_global(|tcx| deadlock(tcx, &registry)))
443-
})
444-
})
442+
syntax::GLOBALS.set(syntax_globals, || {
443+
syntax_pos::GLOBALS
444+
.set(syntax_pos_globals, || tls::with_global(|tcx| deadlock(tcx, &registry)))
445+
});
445446
})
446447
});
447448
}

Diff for: src/librustc_data_structures/atomic_ref.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use std::marker::PhantomData;
2+
use std::sync::atomic::{AtomicPtr, Ordering};
3+
4+
/// This is essentially an `AtomicPtr` but is guaranteed to always be valid
5+
pub struct AtomicRef<T: 'static>(AtomicPtr<T>, PhantomData<&'static T>);
6+
7+
impl<T: 'static> AtomicRef<T> {
8+
pub const fn new(initial: &'static T) -> AtomicRef<T> {
9+
AtomicRef(AtomicPtr::new(initial as *const T as *mut T), PhantomData)
10+
}
11+
12+
pub fn swap(&self, new: &'static T) -> &'static T {
13+
// We never allow storing anything but a `'static` reference so it's safe to
14+
// return it for the same.
15+
unsafe { &*self.0.swap(new as *const T as *mut T, Ordering::SeqCst) }
16+
}
17+
}
18+
19+
impl<T: 'static> std::ops::Deref for AtomicRef<T> {
20+
type Target = T;
21+
fn deref(&self) -> &Self::Target {
22+
// We never allow storing anything but a `'static` reference so it's safe to lend
23+
// it out for any amount of time.
24+
unsafe { &*self.0.load(Ordering::SeqCst) }
25+
}
26+
}

Diff for: src/librustc_data_structures/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,12 @@ pub mod thin_vec;
8989
pub mod tiny_list;
9090
pub mod transitive_relation;
9191
pub use ena::unify;
92+
mod atomic_ref;
9293
pub mod fingerprint;
9394
pub mod profiling;
9495
pub mod vec_linked_list;
9596
pub mod work_queue;
97+
pub use atomic_ref::AtomicRef;
9698

9799
pub struct OnDrop<F: Fn()>(pub F);
98100

Diff for: src/librustc_errors/lib.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ use registry::Registry;
1717
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
1818
use rustc_data_structures::stable_hasher::StableHasher;
1919
use rustc_data_structures::sync::{self, Lock, Lrc};
20+
use rustc_data_structures::AtomicRef;
2021
use syntax_pos::source_map::SourceMap;
2122
use syntax_pos::{Loc, MultiSpan, Span};
2223

2324
use std::borrow::Cow;
24-
use std::cell::Cell;
2525
use std::panic;
2626
use std::path::Path;
2727
use std::{error, fmt};
@@ -309,8 +309,8 @@ pub enum StashKey {
309309

310310
fn default_track_diagnostic(_: &Diagnostic) {}
311311

312-
thread_local!(pub static TRACK_DIAGNOSTICS: Cell<fn(&Diagnostic)> =
313-
Cell::new(default_track_diagnostic));
312+
pub static TRACK_DIAGNOSTICS: AtomicRef<fn(&Diagnostic)> =
313+
AtomicRef::new(&(default_track_diagnostic as fn(&_)));
314314

315315
#[derive(Copy, Clone, Default)]
316316
pub struct HandlerFlags {
@@ -730,9 +730,7 @@ impl HandlerInner {
730730
return;
731731
}
732732

733-
TRACK_DIAGNOSTICS.with(|track_diagnostics| {
734-
track_diagnostics.get()(diagnostic);
735-
});
733+
(*TRACK_DIAGNOSTICS)(diagnostic);
736734

737735
if let Some(ref code) = diagnostic.code {
738736
self.emitted_diagnostic_codes.insert(code.clone());

Diff for: src/librustc_interface/callbacks.rs

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! Throughout the compiler tree, there are several places which want to have
2+
//! access to state or queries while being inside crates that are dependencies
3+
//! of librustc. To facilitate this, we have the
4+
//! `rustc_data_structures::AtomicRef` type, which allows us to setup a global
5+
//! static which can then be set in this file at program startup.
6+
//!
7+
//! See `SPAN_DEBUG` for an example of how to set things up.
8+
//!
9+
//! The functions in this file should fall back to the default set in their
10+
//! origin crate when the `TyCtxt` is not present in TLS.
11+
12+
use rustc::ty::tls;
13+
use rustc_errors::{Diagnostic, TRACK_DIAGNOSTICS};
14+
use std::fmt;
15+
use syntax_pos;
16+
17+
/// This is a callback from libsyntax as it cannot access the implicit state
18+
/// in librustc otherwise.
19+
fn span_debug(span: syntax_pos::Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20+
tls::with_opt(|tcx| {
21+
if let Some(tcx) = tcx {
22+
write!(f, "{}", tcx.sess.source_map().span_to_string(span))
23+
} else {
24+
syntax_pos::default_span_debug(span, f)
25+
}
26+
})
27+
}
28+
29+
/// This is a callback from libsyntax as it cannot access the implicit state
30+
/// in librustc otherwise. It is used to when diagnostic messages are
31+
/// emitted and stores them in the current query, if there is one.
32+
fn track_diagnostic(diagnostic: &Diagnostic) {
33+
tls::with_context_opt(|icx| {
34+
if let Some(icx) = icx {
35+
if let Some(ref diagnostics) = icx.diagnostics {
36+
let mut diagnostics = diagnostics.lock();
37+
diagnostics.extend(Some(diagnostic.clone()));
38+
}
39+
}
40+
})
41+
}
42+
43+
/// Sets up the callbacks in prior crates which we want to refer to the
44+
/// TyCtxt in.
45+
pub fn setup_callbacks() {
46+
syntax_pos::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
47+
TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_)));
48+
}

Diff for: src/librustc_interface/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#[cfg(unix)]
1212
extern crate libc;
1313

14+
mod callbacks;
1415
pub mod interface;
1516
mod passes;
1617
mod proc_macro_decls;

Diff for: src/librustc_interface/util.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -145,13 +145,15 @@ pub fn spawn_thread_pool<F: FnOnce() -> R + Send, R: Send>(
145145
cfg = cfg.stack_size(size);
146146
}
147147

148+
crate::callbacks::setup_callbacks();
149+
148150
scoped_thread(cfg, || {
149151
syntax::with_globals(edition, || {
150152
ty::tls::GCX_PTR.set(&Lock::new(0), || {
151153
if let Some(stderr) = stderr {
152154
io::set_panic(Some(box Sink(stderr.clone())));
153155
}
154-
ty::tls::with_thread_locals(|| f())
156+
f()
155157
})
156158
})
157159
})
@@ -167,6 +169,7 @@ pub fn spawn_thread_pool<F: FnOnce() -> R + Send, R: Send>(
167169
use rayon::{ThreadBuilder, ThreadPool, ThreadPoolBuilder};
168170

169171
let gcx_ptr = &Lock::new(0);
172+
crate::callbacks::setup_callbacks();
170173

171174
let mut config = ThreadPoolBuilder::new()
172175
.thread_name(|_| "rustc".to_string())
@@ -194,9 +197,7 @@ pub fn spawn_thread_pool<F: FnOnce() -> R + Send, R: Send>(
194197
if let Some(stderr) = stderr {
195198
io::set_panic(Some(box Sink(stderr.clone())));
196199
}
197-
ty::tls::with_thread_locals(|| {
198-
ty::tls::GCX_PTR.set(gcx_ptr, || thread.run())
199-
})
200+
ty::tls::GCX_PTR.set(gcx_ptr, || thread.run())
200201
})
201202
})
202203
};

Diff for: src/libsyntax_pos/lib.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#![feature(specialization)]
1414
#![feature(step_trait)]
1515

16+
use rustc_data_structures::AtomicRef;
1617
use rustc_macros::HashStable_Generic;
1718
use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
1819

@@ -41,7 +42,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
4142
use rustc_data_structures::sync::{Lock, Lrc};
4243

4344
use std::borrow::Cow;
44-
use std::cell::{Cell, RefCell};
45+
use std::cell::RefCell;
4546
use std::cmp::{self, Ordering};
4647
use std::fmt;
4748
use std::hash::{Hash, Hasher};
@@ -665,13 +666,13 @@ pub fn default_span_debug(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result
665666

666667
impl fmt::Debug for Span {
667668
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
668-
SPAN_DEBUG.with(|span_debug| span_debug.get()(*self, f))
669+
(*SPAN_DEBUG)(*self, f)
669670
}
670671
}
671672

672673
impl fmt::Debug for SpanData {
673674
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
674-
SPAN_DEBUG.with(|span_debug| span_debug.get()(Span::new(self.lo, self.hi, self.ctxt), f))
675+
(*SPAN_DEBUG)(Span::new(self.lo, self.hi, self.ctxt), f)
675676
}
676677
}
677678

@@ -1503,8 +1504,8 @@ pub struct FileLines {
15031504
pub lines: Vec<LineInfo>,
15041505
}
15051506

1506-
thread_local!(pub static SPAN_DEBUG: Cell<fn(Span, &mut fmt::Formatter<'_>) -> fmt::Result> =
1507-
Cell::new(default_span_debug));
1507+
pub static SPAN_DEBUG: AtomicRef<fn(Span, &mut fmt::Formatter<'_>) -> fmt::Result> =
1508+
AtomicRef::new(&(default_span_debug as fn(_, &mut fmt::Formatter<'_>) -> _));
15081509

15091510
#[derive(Debug)]
15101511
pub struct MacroBacktrace {

0 commit comments

Comments
 (0)