Coverage Report

Created: 2025-04-19 16:54

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