Coverage Report

Created: 2024-11-20 10:13

/build/source/nativelink-util/src/origin_context.rs
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2024 The NativeLink Authors. All rights reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//    http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
use core::panic;
16
use std::any::Any;
17
use std::cell::RefCell;
18
use std::clone::Clone;
19
use std::collections::HashMap;
20
use std::mem::ManuallyDrop;
21
use std::pin::Pin;
22
use std::ptr::from_ref;
23
use std::sync::Arc;
24
use std::task::{Context, Poll};
25
26
use futures::Future;
27
use nativelink_error::{make_err, Code, Error};
28
use pin_project_lite::pin_project;
29
use tracing::instrument::Instrumented;
30
use tracing::{Instrument, Span};
31
32
use crate::background_spawn;
33
34
/// Make a symbol that represents a unique memory pointer that is
35
/// constant and chosen at compile time. This enables two modules
36
/// to use that memory location to reference data that lives in a
37
/// shared module without the two modules knowing about each other.
38
/// For example, let's say we have a context that holds anonymous
39
/// data; we can use these symbols to let one module set the data
40
/// and tie the data to a symbol and another module read the data
41
/// with the symbol, without the two modules knowing about each other.
42
#[macro_export]
43
macro_rules! make_symbol {
44
    ($name:ident, $type:ident) => {
45
        #[no_mangle]
46
        #[used]
47
        pub static $name: $crate::origin_context::NLSymbol<$type> =
48
            $crate::origin_context::NLSymbol {
49
                name: concat!(module_path!(), "::", stringify!($name)),
50
                _phantom: std::marker::PhantomData {},
51
            };
52
    };
53
}
54
55
pub struct NLSymbol<T: Send + Sync + 'static> {
56
    pub name: &'static str,
57
    pub _phantom: std::marker::PhantomData<T>,
58
}
59
60
impl<T: Send + Sync + 'static> Symbol for NLSymbol<T> {
61
    type Type = T;
62
63
0
    fn name(&self) -> &'static str {
64
0
        self.name
65
0
    }
66
}
67
68
pub type RawSymbol = std::os::raw::c_void;
69
70
pub trait Symbol {
71
    type Type: 'static;
72
73
0
    fn name(&self) -> &'static str {
74
0
        std::any::type_name::<Self>()
75
0
    }
76
77
45
    fn as_ptr(&'static self) -> *const RawSymbol {
78
45
        from_ref::<Self>(self).cast::<RawSymbol>()
79
45
    }
80
}
81
82
/// Simple wrapper around a raw symbol pointer.
83
/// This allows us to bypass the unsafe undefined behavior check
84
/// when using raw pointers by manually implementing Send and Sync.
85
#[derive(Eq, PartialEq, Hash, Clone)]
86
#[repr(transparent)]
87
pub struct RawSymbolWrapper(pub *const RawSymbol);
88
89
unsafe impl Send for RawSymbolWrapper {}
90
unsafe impl Sync for RawSymbolWrapper {}
91
92
/// Context used to store data about the origin of a request.
93
#[derive(Default, Clone)]
94
pub struct OriginContext {
95
    data: HashMap<RawSymbolWrapper, Arc<dyn Any + Send + Sync + 'static>>,
96
}
97
98
impl OriginContext {
99
    /// Creates a new (empty) context.
100
301
    pub fn new() -> Self {
101
301
        Self::default()
102
301
    }
103
104
    /// Sets the value for a given symbol on the context.
105
40
    pub fn set_value<T: Any + Send + Sync + 'static>(
106
40
        &mut self,
107
40
        symbol: &'static impl Symbol<Type = T>,
108
40
        value: Arc<T>,
109
40
    ) -> Option<Arc<dyn Any + Send + Sync + 'static>> {
110
40
        self.data.insert(RawSymbolWrapper(symbol.as_ptr()), value)
111
40
    }
112
113
    /// Gets the value current set for a given symbol on the context.
114
    #[inline]
115
5
    pub fn get_value<T: Send + Sync + 'static>(
116
5
        &self,
117
5
        symbol: &'static impl Symbol<Type = T>,
118
5
    ) -> Result<Option<Arc<T>>, Error> {
119
5
        self.data
120
5
            .get(&RawSymbolWrapper(symbol.as_ptr()))
121
5
            .map_or(Ok(None), |value| {
122
2
                Arc::downcast::<T>(value.clone()).map_or_else(
123
2
                    |_| {
124
0
                        Err(make_err!(
125
0
                            Code::Internal,
126
0
                            "Failed to downcast symbol: {}",
127
0
                            symbol.name(),
128
0
                        ))
129
2
                    },
130
2
                    |v| Ok(Some(v)),
131
2
                )
132
5
            })
133
5
    }
134
135
    /// Consumes the context and runs the given function with the context set
136
    /// as the active context. When the function exits, the context is restored
137
    /// to the previous global context.
138
    #[inline]
139
4
    pub fn run<T>(self, span: Span, func: impl FnOnce() -> T) -> T {
140
4
        Arc::new(self).wrap(span, func)()
141
4
    }
142
143
    /// Wraps a function so when it is called the passed in context is set as
144
    /// the active context and when the function exits, the context is restored
145
    /// to the previous global context.
146
    #[inline]
147
4
    fn wrap<T>(self: Arc<Self>, span: Span, func: impl FnOnce() -> T) -> impl FnOnce() -> T {
148
4
        move || {
149
4
            let enter = Self::enter(self);
150
4
            let result = span.in_scope(func);
151
4
            enter.release();
152
4
            result
153
4
        }
154
4
    }
155
156
    /// Wraps a future so when it is called the passed in context is set as
157
    /// the active context and when the future exits, the context is restored
158
    /// to the previous global context.
159
    #[inline]
160
337
    pub fn wrap_async<T>(
161
337
        self: Arc<Self>,
162
337
        span: Span,
163
337
        fut: impl Future<Output = T>,
164
337
    ) -> impl Future<Output = T> {
165
337
        ContextAwareFuture::new(Some(self), fut.instrument(span))
166
337
    }
167
168
    /// Spawns a future in the background with the given context.
169
0
    pub fn background_spawn(
170
0
        self: Arc<Self>,
171
0
        span: Span,
172
0
        fut: impl Future<Output = ()> + Send + 'static,
173
0
    ) {
174
0
        background_spawn!(span: span, ctx: Some(self), fut: fut);
175
0
    }
176
177
    /// Enters the context, storing the previous context. If the returned
178
    /// `ContextDropGuard` is dropped, the previous context is restored.
179
    #[inline]
180
16.6k
    fn enter(self: Arc<Self>) -> ContextDropGuard {
181
16.6k
        ContextDropGuard::new(self)
182
16.6k
    }
183
}
184
185
/// Static struct to interact with the active global context.
186
pub struct ActiveOriginContext;
187
188
impl ActiveOriginContext {
189
    /// Sets the active context for the current thread.
190
1.47k
    pub fn get() -> Option<Arc<OriginContext>> {
191
1.47k
        GLOBAL_ORIGIN_CONTEXT.with_borrow(Clone::clone)
192
1.47k
    }
193
194
    /// Gets the value current set for a given symbol on the
195
    /// active context.
196
    #[inline]
197
5
    pub fn get_value<T: Send + Sync + 'static>(
198
5
        symbol: &'static impl Symbol<Type = T>,
199
5
    ) -> Result<Option<Arc<T>>, Error> {
200
5
        GLOBAL_ORIGIN_CONTEXT.with_borrow(|maybe_ctx| {
201
5
            maybe_ctx.as_ref().map_or_else(
202
5
                || {
203
0
                    Err(make_err!(
204
0
                        Code::Internal,
205
0
                        "Expected active context to be set"
206
0
                    ))
207
5
                },
208
5
                |ctx| ctx.get_value(symbol),
209
5
            )
210
5
        })
211
5
    }
212
213
    /// Forks the active context, returning a new context with the same data.
214
    #[inline]
215
40
    pub fn fork() -> Result<OriginContext, Error> {
216
40
        GLOBAL_ORIGIN_CONTEXT.with_borrow(|maybe_ctx| {
217
40
            maybe_ctx.as_ref().map_or_else(
218
40
                || {
219
0
                    Err(make_err!(
220
0
                        Code::Internal,
221
0
                        "Expected active context to be set"
222
0
                    ))
223
40
                },
224
40
                |ctx| Ok(ctx.as_ref().clone()),
225
40
            )
226
40
        })
227
40
    }
228
}
229
230
thread_local! {
231
  /// Global context that is used to store the active context.
232
  static GLOBAL_ORIGIN_CONTEXT: RefCell<Option<Arc<OriginContext>>> = const { RefCell::new(None) };
233
}
234
235
/// Special guard struct that is used to hold the previous context and restore it
236
/// when the guard is released or dropped.
237
struct ContextDropGuard {
238
    prev_ctx: Option<Arc<OriginContext>>,
239
    new_ctx_ptr: *const OriginContext,
240
}
241
242
impl ContextDropGuard {
243
    /// Places the new context in the global context, stores the previous context
244
    /// and returns a new `ContextDropGuard`, so if it is ever released or dropped
245
    /// the previous context will be restored.
246
    #[inline]
247
16.6k
    fn new(new_ctx: Arc<OriginContext>) -> Self {
248
16.6k
        let new_ctx_ptr = Arc::as_ptr(&new_ctx);
249
16.6k
        let prev_ctx = GLOBAL_ORIGIN_CONTEXT.replace(Some(new_ctx));
250
16.6k
        Self {
251
16.6k
            prev_ctx,
252
16.6k
            new_ctx_ptr,
253
16.6k
        }
254
16.6k
    }
255
256
    /// Swap the global context with the previous context.
257
    /// Returns the context used in the `.enter()`/`.new()` call.
258
16.6k
    fn restore_global_context(&mut self) -> Arc<OriginContext> {
259
16.6k
        let new_ctx = GLOBAL_ORIGIN_CONTEXT
260
16.6k
            .replace(self.prev_ctx.take())
261
16.6k
            .expect("Expected global context to be set");
262
16.6k
        assert_eq!(self.new_ctx_ptr, Arc::as_ptr(&new_ctx));
263
16.6k
        new_ctx
264
16.6k
    }
265
266
    /// Release the context guard and restore the previous context.
267
    /// This is an optimization, so we don't need to clone our Arc
268
    /// if the caller can use the context after releasing it.
269
    #[inline]
270
14.8k
    fn release(mut self) -> Arc<OriginContext> {
271
14.8k
        let new_ctx = self.restore_global_context();
272
14.8k
        std::mem::forget(self); // Prevent the destructor from being called.
273
14.8k
        new_ctx
274
14.8k
    }
275
}
276
277
impl Drop for ContextDropGuard {
278
    #[inline]
279
1.80k
    fn drop(&mut self) {
280
1.80k
        // If the user calls `.release()` the drop() will not be triggered.
281
1.80k
        // If a panic happens, the drop() will be called and the `.release()`
282
1.80k
        // will not be called, this is our safety net.
283
1.80k
        self.restore_global_context();
284
1.80k
    }
285
}
286
287
pin_project! {
288
    #[must_use = "futures do nothing unless you `.await` or poll them"]
289
    pub struct ContextAwareFuture<F> {
290
        // `ManuallyDrop` is used so we can call `self.span.enter()` in the `drop()`
291
        // of our inner future, then drop the span.
292
        #[pin]
293
        inner: ManuallyDrop<Instrumented<F>>,
294
        context: Option<Arc<OriginContext>>,
295
    }
296
297
    impl <F> PinnedDrop for ContextAwareFuture<F> {
298
        #[inline]
299
        fn drop(this: Pin<&mut Self>) {
300
            let this = this.project();
301
            // Note: If the future panics, the context will not be restored, so
302
            // this is a best effort to provide access to our global context
303
            // in the destructors the event of a panic.
304
            let _enter = this.context.take().map(OriginContext::enter);
305
            // SAFETY: 1. `Pin::get_unchecked_mut()` is safe, because this isn't
306
            //             different from wrapping `T` in `Option` and calling
307
            //             `Pin::set(&mut this.inner, None)`, except avoiding
308
            //             additional memory overhead.
309
            //         2. `ManuallyDrop::drop()` is safe, because
310
            //            `PinnedDrop::drop()` is guaranteed to be called only
311
            //            once.
312
            unsafe {
313
                ManuallyDrop::drop(this.inner.get_unchecked_mut());
314
            }
315
        }
316
    }
317
}
318
319
impl<T> ContextAwareFuture<T> {
320
    /// Utility function to create a new `ContextAwareFuture` from the
321
    /// active context.
322
    #[must_use = "futures do nothing unless you `.await` or poll them"]
323
    #[inline]
324
9
    pub fn new_from_active(inner: Instrumented<T>) -> ContextAwareFuture<T> {
325
9
        if let Some(ctx) = ActiveOriginContext::get() {
  Branch (325:16): [Folded - Ignored]
  Branch (325:16): [True: 2, False: 0]
  Branch (325:16): [True: 2, False: 0]
  Branch (325:16): [True: 2, False: 0]
  Branch (325:16): [True: 2, False: 0]
  Branch (325:16): [True: 1, False: 0]
  Branch (325:16): [Folded - Ignored]
326
9
            ContextAwareFuture::new(Some(ctx), inner)
327
        } else {
328
            // Useful to get tracing stack trace.
329
0
            tracing::error!("OriginContext must be set");
330
0
            panic!("OriginContext must be set");
331
        }
332
9
    }
333
334
    #[must_use = "futures do nothing unless you `.await` or poll them"]
335
    #[inline]
336
1.80k
    pub(crate) fn new(context: Option<Arc<OriginContext>>, inner: Instrumented<T>) -> Self {
337
1.80k
        Self {
338
1.80k
            inner: ManuallyDrop::new(inner),
339
1.80k
            context,
340
1.80k
        }
341
1.80k
    }
342
}
343
344
impl<T: Future> Future for ContextAwareFuture<T> {
345
    type Output = T::Output;
346
347
    #[inline]
348
14.8k
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
349
14.8k
        let this = self.project();
350
14.8k
        let Some(ctx) = this.context.take() else {
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 22, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 115, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 32, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 54, False: 0]
  Branch (350:13): [True: 1.22k, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 26, False: 0]
  Branch (350:13): [Folded - Ignored]
  Branch (350:13): [True: 74, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 706, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 290, False: 0]
  Branch (350:13): [True: 67, False: 0]
  Branch (350:13): [True: 270, False: 0]
  Branch (350:13): [True: 13, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 15, False: 0]
  Branch (350:13): [True: 13, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 7, False: 0]
  Branch (350:13): [True: 13, False: 0]
  Branch (350:13): [True: 7, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 2.63k, False: 0]
  Branch (350:13): [True: 83, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 32, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 31, False: 0]
  Branch (350:13): [True: 3.26k, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 25, False: 0]
  Branch (350:13): [True: 1.02k, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 16, False: 0]
  Branch (350:13): [True: 16, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 48, False: 0]
  Branch (350:13): [True: 42, False: 0]
  Branch (350:13): [True: 45, False: 0]
  Branch (350:13): [True: 41, False: 0]
  Branch (350:13): [True: 42, False: 0]
  Branch (350:13): [True: 1.03k, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 19, False: 0]
  Branch (350:13): [True: 15, False: 0]
  Branch (350:13): [True: 19, False: 0]
  Branch (350:13): [True: 11, False: 0]
  Branch (350:13): [True: 10, False: 0]
  Branch (350:13): [True: 23, False: 0]
  Branch (350:13): [True: 14, False: 0]
  Branch (350:13): [True: 13, False: 0]
  Branch (350:13): [True: 28, False: 0]
  Branch (350:13): [True: 19, False: 0]
  Branch (350:13): [True: 19, False: 0]
  Branch (350:13): [True: 10, False: 0]
  Branch (350:13): [True: 28, False: 0]
  Branch (350:13): [True: 22, False: 0]
  Branch (350:13): [True: 16, False: 0]
  Branch (350:13): [True: 33, False: 0]
  Branch (350:13): [True: 21, False: 0]
  Branch (350:13): [True: 15, False: 0]
  Branch (350:13): [True: 13, False: 0]
  Branch (350:13): [True: 16, False: 0]
  Branch (350:13): [True: 17, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 18, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 9, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 9, False: 0]
  Branch (350:13): [True: 8, False: 0]
  Branch (350:13): [True: 12, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 24, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 10, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [Folded - Ignored]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 12, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 8, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 8, False: 0]
  Branch (350:13): [True: 9, False: 0]
  Branch (350:13): [True: 11, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 41, False: 0]
  Branch (350:13): [True: 74, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 39, False: 0]
  Branch (350:13): [True: 80, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 40, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 38, False: 0]
  Branch (350:13): [True: 16, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 43, False: 0]
  Branch (350:13): [True: 28, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 10, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 17, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 51, False: 0]
  Branch (350:13): [True: 52, False: 0]
  Branch (350:13): [True: 11, False: 0]
  Branch (350:13): [True: 11, False: 0]
  Branch (350:13): [True: 57, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 26, False: 0]
  Branch (350:13): [True: 7, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 51, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 24, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 24, False: 0]
  Branch (350:13): [True: 24, False: 0]
  Branch (350:13): [True: 24, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 24, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 502, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 993, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 0, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 6, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 5, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 73, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 3, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 4, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 2, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
  Branch (350:13): [True: 1, False: 0]
351
            // Useful to get tracing stack trace.
352
0
            tracing::error!("Expected context to be set");
353
0
            panic!("Expected context to be set");
354
        };
355
14.8k
        let enter = ctx.enter();
356
14.8k
        // Since `inner` is only moved when the future itself is dropped, `inner` will
357
14.8k
        // never move, so this should be safe.
358
14.8k
        // see: https://docs.rs/tracing/0.1.40/src/tracing/instrument.rs.html#297
359
14.8k
        let inner = unsafe { this.inner.map_unchecked_mut(|v| &mut **v) };
360
14.8k
        let result = inner.poll(cx);
361
14.8k
        assert!(
362
14.8k
            this.context.replace(enter.release()).is_none(),
363
0
            "Expected context to be unset"
364
        );
365
14.8k
        result
366
14.8k
    }
367
}