Coverage Report

Created: 2025-03-08 07:13

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