|
1 | 1 | use std::cell::Cell; |
2 | | -use std::ptr; |
| 2 | +use std::ptr::{self, NonNull}; |
3 | 3 |
|
4 | 4 | use rustc_ast::tokenstream::TokenStream; |
5 | 5 | use rustc_data_structures::svh::Svh; |
@@ -56,70 +56,47 @@ thread_local! { |
56 | 56 | static TLV: Cell<(*mut (), Option<CLIENT>)> = const { Cell::new((ptr::null_mut(), None)) }; |
57 | 57 | } |
58 | 58 |
|
| 59 | +/// Sets `context` as the new current `CONTEXT` for the duration of the function `f`. |
59 | 60 | #[inline] |
60 | | -fn erase(context: &mut ExtCtxt<'_>) -> *mut () { |
61 | | - context as *mut _ as *mut () |
62 | | -} |
63 | | - |
64 | | -#[inline] |
65 | | -unsafe fn downcast<'a>(context: *mut ()) -> &'a mut ExtCtxt<'a> { |
66 | | - unsafe { &mut *(context as *mut ExtCtxt<'a>) } |
67 | | -} |
68 | | - |
69 | | -#[inline] |
70 | | -fn enter_context_erased<F, R>(erased: (*mut (), Option<CLIENT>), f: F) -> R |
| 61 | +pub(crate) fn enter_context<'a, F, R>(context: (&mut ExtCtxt<'a>, CLIENT), f: F) -> R |
71 | 62 | where |
72 | 63 | F: FnOnce() -> R, |
73 | 64 | { |
| 65 | + let (ectx, client) = context; |
| 66 | + let erased = (ectx as *mut _ as *mut (), Some(client)); |
74 | 67 | TLV.with(|tlv| { |
75 | 68 | let old = tlv.replace(erased); |
76 | 69 | let _reset = rustc_data_structures::defer(move || tlv.set(old)); |
77 | 70 | f() |
78 | 71 | }) |
79 | 72 | } |
80 | 73 |
|
81 | | -/// Sets `context` as the new current `CONTEXT` for the duration of the function `f`. |
82 | | -#[inline] |
83 | | -pub fn enter_context<'a, F, R>(context: (&mut ExtCtxt<'a>, CLIENT), f: F) -> R |
84 | | -where |
85 | | - F: FnOnce() -> R, |
86 | | -{ |
87 | | - let (ectx, client) = context; |
88 | | - let erased = (erase(ectx), Some(client)); |
89 | | - enter_context_erased(erased, f) |
90 | | -} |
91 | | - |
92 | | -/// Allows access to the current `CONTEXT` in a closure if one is available. |
| 74 | +/// Allows access to the current `CONTEXT`. |
| 75 | +/// Panics if there is no `CONTEXT` available. |
93 | 76 | #[inline] |
94 | 77 | #[track_caller] |
95 | | -pub fn with_context_opt<F, R>(f: F) -> R |
| 78 | +fn with_context<F, R>(f: F) -> R |
96 | 79 | where |
97 | | - F: for<'a, 'b> FnOnce(Option<&'b mut (&mut ExtCtxt<'a>, CLIENT)>) -> R, |
| 80 | + F: for<'a, 'b> FnOnce(&'b mut (&mut ExtCtxt<'a>, CLIENT)) -> R, |
98 | 81 | { |
99 | 82 | let (ectx, client_opt) = TLV.get(); |
100 | | - if ectx.is_null() { |
101 | | - f(None) |
102 | | - } else { |
103 | | - // We could get an `CONTEXT` pointer from another thread. |
104 | | - // Ensure that `CONTEXT` is `DynSync`. |
105 | | - // FIXME(pr-time): we should not be able to? |
106 | | - // sync::assert_dyn_sync::<CONTEXT<'_>>(); |
| 83 | + let ectx = NonNull::new(ectx).expect("no CONTEXT stored in tls"); |
107 | 84 |
|
108 | | - // prevent double entering, as that would allow creating two `&mut ExtCtxt`s |
109 | | - // FIXME(pr-time): probably use a RefCell instead (which checks this properly)? |
110 | | - enter_context_erased((ptr::null_mut(), None), || unsafe { |
111 | | - let ectx = downcast(ectx); |
112 | | - f(Some(&mut (ectx, client_opt.unwrap()))) |
113 | | - }) |
114 | | - } |
115 | | -} |
| 85 | + // We could get an `CONTEXT` pointer from another thread. |
| 86 | + // Ensure that `CONTEXT` is `DynSync`. |
| 87 | + // FIXME(pr-time): we should not be able to? |
| 88 | + // sync::assert_dyn_sync::<CONTEXT<'_>>(); |
116 | 89 |
|
117 | | -/// Allows access to the current `CONTEXT`. |
118 | | -/// Panics if there is no `CONTEXT` available. |
119 | | -#[inline] |
120 | | -pub fn with_context<F, R>(f: F) -> R |
121 | | -where |
122 | | - F: for<'a, 'b> FnOnce(&'b mut (&mut ExtCtxt<'a>, CLIENT)) -> R, |
123 | | -{ |
124 | | - with_context_opt(|opt_context| f(opt_context.expect("no CONTEXT stored in tls"))) |
| 90 | + // prevent double entering, as that would allow creating two `&mut ExtCtxt`s |
| 91 | + // FIXME(pr-time): probably use a RefCell instead (which checks this properly)? |
| 92 | + TLV.with(|tlv| { |
| 93 | + let old = tlv.replace((ptr::null_mut(), None)); |
| 94 | + let _reset = rustc_data_structures::defer(move || tlv.set(old)); |
| 95 | + let ectx = { |
| 96 | + let mut casted = ectx.cast::<ExtCtxt<'_>>(); |
| 97 | + unsafe { casted.as_mut() } |
| 98 | + }; |
| 99 | + |
| 100 | + f(&mut (ectx, client_opt.unwrap())) |
| 101 | + }) |
125 | 102 | } |
0 commit comments