rustc_middle/ty/context/
tls.rs1use rustc_data_structures::sync;
2
3use super::{GlobalCtxt, TyCtxt};
4use crate::dep_graph::TaskDepsRef;
5use crate::query::QueryJobId;
6
7pub struct ImplicitCtxt<'a, 'tcx> {
13 pub tcx: TyCtxt<'tcx>,
15
16 pub query: Option<QueryJobId>,
18
19 pub query_depth: usize,
21
22 pub task_deps: TaskDepsRef<'a>,
25}
26
27impl<'a, 'tcx> ImplicitCtxt<'a, 'tcx> {
28 pub fn new(gcx: &'tcx GlobalCtxt<'tcx>) -> Self {
29 let tcx = TyCtxt { gcx };
30 ImplicitCtxt { tcx, query: None, query_depth: 0, task_deps: TaskDepsRef::Ignore }
31 }
32}
33
34use rustc_thread_pool::tlv::TLV;
36
37#[inline]
38fn erase(context: &ImplicitCtxt<'_, '_>) -> *const () {
39 context as *const _ as *const ()
40}
41
42#[inline]
43unsafe fn downcast<'a, 'tcx>(context: *const ()) -> &'a ImplicitCtxt<'a, 'tcx> {
44 unsafe { &*(context as *const ImplicitCtxt<'a, 'tcx>) }
45}
46
47#[inline]
49pub fn enter_context<'a, 'tcx, F, R>(context: &ImplicitCtxt<'a, 'tcx>, f: F) -> R
50where
51 F: FnOnce() -> R,
52{
53 TLV.with(|tlv| {
54 let old = tlv.replace(erase(context));
55 let _reset = rustc_data_structures::defer(move || tlv.set(old));
56 f()
57 })
58}
59
60#[inline]
62#[track_caller]
63pub fn with_context_opt<F, R>(f: F) -> R
64where
65 F: for<'a, 'tcx> FnOnce(Option<&ImplicitCtxt<'a, 'tcx>>) -> R,
66{
67 let context = TLV.get();
68 if context.is_null() {
69 f(None)
70 } else {
71 sync::assert_dyn_sync::<ImplicitCtxt<'_, '_>>();
74
75 unsafe { f(Some(downcast(context))) }
76 }
77}
78
79#[inline]
82pub fn with_context<F, R>(f: F) -> R
83where
84 F: for<'a, 'tcx> FnOnce(&ImplicitCtxt<'a, 'tcx>) -> R,
85{
86 with_context_opt(|opt_context| f(opt_context.expect("no ImplicitCtxt stored in tls")))
87}
88
89#[inline]
92pub fn with<F, R>(f: F) -> R
93where
94 F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> R,
95{
96 with_context(|context| f(context.tcx))
97}
98
99#[inline]
102#[track_caller]
103pub fn with_opt<F, R>(f: F) -> R
104where
105 F: for<'tcx> FnOnce(Option<TyCtxt<'tcx>>) -> R,
106{
107 with_context_opt(
108 #[track_caller]
109 |opt_context| f(opt_context.map(|context| context.tcx)),
110 )
111}