Coverage Report

Created: 2024-12-19 04:04

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