|
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